[clang] [X86_64] fix arg pass error in struct. (PR #85394)
https://github.com/CoTinker created https://github.com/llvm/llvm-project/pull/85394 typedef long long Alignll __attribute__((align (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. fix #85387. >From 8efa87d7b03ebf2cf304e97c5fcebdb4211350b4 Mon Sep 17 00:00:00 2001 From: Longsheng Mou Date: Fri, 15 Mar 2024 20:50:54 +0800 Subject: [PATCH] [X86_64] fix arg pass error in struct. typedef long long Alignll __attribute__((align (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 | 5 + clang/test/CodeGen/X86/x86_64-arguments.c | 18 ++ 2 files changed, 23 insertions(+) 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()) { @@ -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: ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [X86_64] fix arg pass error in struct. (PR #85394)
https://github.com/CoTinker edited https://github.com/llvm/llvm-project/pull/85394 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [X86_64] fix arg pass error in struct. (PR #85394)
https://github.com/CoTinker edited https://github.com/llvm/llvm-project/pull/85394 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [X86_64] fix arg pass error in struct. (PR #85394)
https://github.com/CoTinker updated https://github.com/llvm/llvm-project/pull/85394 >From 30d8d0490b383b8b52fee7d8ddd591f8ed5b585e Mon Sep 17 00:00:00 2001 From: Longsheng Mou Date: Fri, 15 Mar 2024 20:50:54 +0800 Subject: [PATCH] [X86_64] fix arg pass error in struct. typedef long long Alignll __attribute__((align (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()) { @@ -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..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: ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [X86_64] fix arg pass error in struct. (PR #85394)
https://github.com/CoTinker edited https://github.com/llvm/llvm-project/pull/85394 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [X86_64] fix arg pass error in struct. (PR #85394)
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 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()) { @@ -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: ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [X86_64] fix arg pass error in struct. (PR #85394)
https://github.com/CoTinker edited https://github.com/llvm/llvm-project/pull/85394 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [X86_64] fix arg pass error in struct. (PR #85394)
https://github.com/CoTinker edited https://github.com/llvm/llvm-project/pull/85394 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [X86_64] fix arg pass error in struct. (PR #85394)
https://github.com/CoTinker updated https://github.com/llvm/llvm-project/pull/85394 >From be6b4bdd75554b9287092ab42063a9d4e260dd9c Mon Sep 17 00:00:00 2001 From: Longsheng Mou 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()) { @@ -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: ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [X86_64] fix arg pass error in struct. (PR #85394)
https://github.com/CoTinker updated https://github.com/llvm/llvm-project/pull/85394 >From 1ca19591fa11a53559fdfe7e4bf6b298b7658628 Mon Sep 17 00:00:00 2001 From: Longsheng Mou 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()) { @@ -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: ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [X86_64] fix arg pass error in struct. (PR #85394)
https://github.com/CoTinker updated https://github.com/llvm/llvm-project/pull/85394 >From 57760b2bfe87c689030975d5914393fd29d7d1f5 Mon Sep 17 00:00:00 2001 From: Longsheng Mou Date: Fri, 15 Mar 2024 20:50:54 +0800 Subject: [PATCH] [X86_64] fix arg pass error in struct. typedef long long ll __attribute__((aligned (4))); struct S { int a; ll 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()) { @@ -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: ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [X86_64] fix empty structure vaarg in c++ (PR #77907)
CoTinker wrote: ping~ https://github.com/llvm/llvm-project/pull/77907 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [X86_64] fix arg pass error in struct. (PR #85394)
https://github.com/CoTinker updated https://github.com/llvm/llvm-project/pull/85394 >From d344d20883a73ef1d273a4b74eb1b5df2893041e Mon Sep 17 00:00:00 2001 From: Longsheng Mou Date: Fri, 15 Mar 2024 20:50:54 +0800 Subject: [PATCH] [X86_64] fix arg pass error in struct. typedef long long ll __attribute__((aligned (4))); struct S { int a; ll 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..d91911ece69683 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()) { @@ -1798,9 +1800,13 @@ void X86_64ABIInfo::classify(QualType Ty, uint64_t OffsetBase, Class &Lo, Lo = Integer; Hi = Integer; } else if (k >= BuiltinType::Bool && k <= BuiltinType::LongLong) { + if (IsSplit) +return; Current = Integer; } else if (k == BuiltinType::Float || k == BuiltinType::Double || k == BuiltinType::Float16 || k == BuiltinType::BFloat16) { + if (IsSplit) +return; Current = SSE; } else if (k == BuiltinType::Float128) { Lo = SSE; diff --git a/clang/test/CodeGen/X86/x86_64-arguments.c b/clang/test/CodeGen/X86/x86_64-arguments.c index cf5636cfd518b6..82845f0a2b31fd 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(ptr noundef byval(%struct.s67) align 8 %x) +void f67(struct s67 x) { +} + +typedef double t68 __attribute__((aligned (4))); +struct s68 { + int a; + t68 b; +}; +// CHECK-LABEL: define{{.*}} void @f68(ptr noundef byval(%struct.s68) align 8 %x) +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: ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [X86_64] fix arg pass error in struct. (PR #85394)
CoTinker wrote: Thanks, I'll modify it according to this. https://github.com/llvm/llvm-project/pull/85394 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [X86_32] Teach X86_32 va_arg to ignore empty structs. (PR #86075)
https://github.com/CoTinker created https://github.com/llvm/llvm-project/pull/86075 Empty structs are ignored for parameter passing purposes, but va_arg was incrementing the pointer anyway for that the size of empty struct in c++ is 1 byte, which could lead to va_list getting out of sync. Fix #86057. >From 944259ba90fc13c04b6bbd44ec1737fbbb56b2d1 Mon Sep 17 00:00:00 2001 From: Longsheng Mou Date: Thu, 21 Mar 2024 11:23:56 +0800 Subject: [PATCH] [X86_32] Teach X86_32 va_arg to ignore empty structs. Empty structs are ignored for parameter passing purposes, but va_arg was incrementing the pointer anyway for that the size of empty struct in c++ is 1 byte, which could lead to va_list getting out of sync. --- clang/lib/CodeGen/Targets/X86.cpp | 4 clang/test/CodeGenCXX/x86_32-vaarg.cpp | 20 2 files changed, 24 insertions(+) create mode 100644 clang/test/CodeGenCXX/x86_32-vaarg.cpp diff --git a/clang/lib/CodeGen/Targets/X86.cpp b/clang/lib/CodeGen/Targets/X86.cpp index 1ec0f159ebcb8a..7931f56ad6835f 100644 --- a/clang/lib/CodeGen/Targets/X86.cpp +++ b/clang/lib/CodeGen/Targets/X86.cpp @@ -1069,6 +1069,10 @@ Address X86_32ABIInfo::EmitVAArg(CodeGenFunction &CGF, auto TypeInfo = getContext().getTypeInfoInChars(Ty); + // Empty records are ignored for parameter passing purposes on non-Windows. + if (!IsWin32StructABI && isEmptyRecord(getContext(), Ty, true)) +return CGF.CreateMemTemp(Ty); + // x86-32 changes the alignment of certain arguments on the stack. // // Just messing with TypeInfo like this works because we never pass diff --git a/clang/test/CodeGenCXX/x86_32-vaarg.cpp b/clang/test/CodeGenCXX/x86_32-vaarg.cpp new file mode 100644 index 00..23eac1164118c6 --- /dev/null +++ b/clang/test/CodeGenCXX/x86_32-vaarg.cpp @@ -0,0 +1,20 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py +// RUN: %clang_cc1 -triple i386-linux-gnu -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -triple i386-linux-gnu -emit-llvm -x c -o - %s | FileCheck %s + +typedef struct {} empty; + +// CHECK-LABEL: @{{.*}}empty_record_test +// CHECK-NEXT: entry: +// CHECK-NEXT:[[RESULT_PTR:%.*]] = alloca ptr, align 4 +// CHECK-NEXT:[[Z_ADDR:%.*]] = alloca i32, align 4 +// CHECK-NEXT:[[LIST:%.*]] = alloca ptr, align 4 +// CHECK-NEXT:[[TMP:%.*]] = alloca [[STRUCT_EMPTY:%.*]], align 1 +// CHECK-NEXT:store ptr [[AGG_RESULT:%.*]], ptr [[RESULT_PTR]], align 4 +// CHECK-NEXT:store i32 [[Z:%.*]], ptr [[Z_ADDR]], align 4 +// CHECK-NEXT:call void @llvm.va_start(ptr [[LIST]]) +empty empty_record_test(int z, ...) { + __builtin_va_list list; + __builtin_va_start(list, z); + return __builtin_va_arg(list, empty); +} ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [X86_64] fix arg pass error in struct. (PR #85394)
CoTinker wrote: Which is more appropriate to pass this structure through, memory or register? https://github.com/llvm/llvm-project/pull/85394 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [X86_32] Teach X86_32 va_arg to ignore empty structs. (PR #86075)
@@ -1069,6 +1069,10 @@ Address X86_32ABIInfo::EmitVAArg(CodeGenFunction &CGF, auto TypeInfo = getContext().getTypeInfoInChars(Ty); + // Empty records are ignored for parameter passing purposes on non-Windows. + if (!IsWin32StructABI && isEmptyRecord(getContext(), Ty, true)) +return CGF.CreateMemTemp(Ty); CoTinker wrote: classifyArgumentType in X86_32 need CCState parameter, but we can not get it in this scope, because the CCState is temporarily calculated in X86_32ABIInfo::computeInfo. https://github.com/llvm/llvm-project/pull/86075 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [X86_64] fix arg pass error in struct. (PR #85394)
https://github.com/CoTinker updated https://github.com/llvm/llvm-project/pull/85394 >From 57cdbcab4ad13441a3f8731c4cdedc51acfbc7b1 Mon Sep 17 00:00:00 2001 From: Longsheng Mou Date: Fri, 15 Mar 2024 20:50:54 +0800 Subject: [PATCH] [X86_64] fix arg pass error in struct. typedef long long ll __attribute__((aligned (4))); struct S { int a; ll 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, 23 insertions(+), 1 deletion(-) diff --git a/clang/lib/CodeGen/Targets/X86.cpp b/clang/lib/CodeGen/Targets/X86.cpp index 2291c991fb1107..de0dfe32a54d3a 100644 --- a/clang/lib/CodeGen/Targets/X86.cpp +++ b/clang/lib/CodeGen/Targets/X86.cpp @@ -2100,8 +2100,12 @@ void X86_64ABIInfo::classify(QualType Ty, uint64_t OffsetBase, Class &Lo, postMerge(Size, Lo, Hi); return; } + + bool InMemory = Offset % getContext().getTypeAlign(i->getType()) || + (i->getType()->getAs() && + Offset % getContext().getTypeSize(i->getType())); // Note, skip this test for bit-fields, see below. - if (!BitField && Offset % getContext().getTypeAlign(i->getType())) { + if (!BitField && InMemory) { Lo = Memory; postMerge(Size, Lo, Hi); return; diff --git a/clang/test/CodeGen/X86/x86_64-arguments.c b/clang/test/CodeGen/X86/x86_64-arguments.c index cf5636cfd518b6..82845f0a2b31fd 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(ptr noundef byval(%struct.s67) align 8 %x) +void f67(struct s67 x) { +} + +typedef double t68 __attribute__((aligned (4))); +struct s68 { + int a; + t68 b; +}; +// CHECK-LABEL: define{{.*}} void @f68(ptr noundef byval(%struct.s68) align 8 %x) +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: ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [X86_64] fix arg pass error in struct. (PR #85394)
https://github.com/CoTinker updated https://github.com/llvm/llvm-project/pull/85394 >From 07e8b31dbe6eaa1a385d52160bf1913c9fa1c17e Mon Sep 17 00:00:00 2001 From: Longsheng Mou Date: Fri, 15 Mar 2024 20:50:54 +0800 Subject: [PATCH] [X86_64] fix arg pass error in struct. 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. --- clang/lib/CodeGen/Targets/X86.cpp | 6 +- clang/test/CodeGen/X86/x86_64-arguments.c | 18 ++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/clang/lib/CodeGen/Targets/X86.cpp b/clang/lib/CodeGen/Targets/X86.cpp index 2291c991fb1107..de0dfe32a54d3a 100644 --- a/clang/lib/CodeGen/Targets/X86.cpp +++ b/clang/lib/CodeGen/Targets/X86.cpp @@ -2100,8 +2100,12 @@ void X86_64ABIInfo::classify(QualType Ty, uint64_t OffsetBase, Class &Lo, postMerge(Size, Lo, Hi); return; } + + bool InMemory = Offset % getContext().getTypeAlign(i->getType()) || + (i->getType()->getAs() && + Offset % getContext().getTypeSize(i->getType())); // Note, skip this test for bit-fields, see below. - if (!BitField && Offset % getContext().getTypeAlign(i->getType())) { + if (!BitField && InMemory) { Lo = Memory; postMerge(Size, Lo, Hi); return; diff --git a/clang/test/CodeGen/X86/x86_64-arguments.c b/clang/test/CodeGen/X86/x86_64-arguments.c index cf5636cfd518b6..82845f0a2b31fd 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(ptr noundef byval(%struct.s67) align 8 %x) +void f67(struct s67 x) { +} + +typedef double t68 __attribute__((aligned (4))); +struct s68 { + int a; + t68 b; +}; +// CHECK-LABEL: define{{.*}} void @f68(ptr noundef byval(%struct.s68) align 8 %x) +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: ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [X86_64] fix SSE type error in vaarg. (PR #86377)
https://github.com/CoTinker created https://github.com/llvm/llvm-project/pull/86377 tweak the position of the ++neededSSE when Lo is NoClass and Hi is SSE. Fix #86371. >From 551d1cd574cdf66a73dbe4e384a21949013e0baa Mon Sep 17 00:00:00 2001 From: Longsheng Mou Date: Sat, 23 Mar 2024 11:52:04 +0800 Subject: [PATCH] [X86_64] fix SSE type error in vaarg. tweak the position of the ++neededSSE when Lo is NoClass and Hi is SSE. --- clang/lib/CodeGen/Targets/X86.cpp | 3 +-- clang/test/CodeGenCXX/x86_64-vaarg.cpp | 15 +++ 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/clang/lib/CodeGen/Targets/X86.cpp b/clang/lib/CodeGen/Targets/X86.cpp index 1ec0f159ebcb8a..6931768147a9b2 100644 --- a/clang/lib/CodeGen/Targets/X86.cpp +++ b/clang/lib/CodeGen/Targets/X86.cpp @@ -2788,12 +2788,11 @@ X86_64ABIInfo::classifyArgumentType(QualType Ty, unsigned freeIntRegs, // memory), except in situations involving unions. case X87Up: case SSE: +++neededSSE; HighPart = GetSSETypeAtOffset(CGT.ConvertType(Ty), 8, Ty, 8); if (Lo == NoClass) // Pass HighPart at offset 8 in memory. return ABIArgInfo::getDirect(HighPart, 8); - -++neededSSE; break; // AMD64-ABI 3.2.3p3: Rule 4. If the class is SSEUP, the diff --git a/clang/test/CodeGenCXX/x86_64-vaarg.cpp b/clang/test/CodeGenCXX/x86_64-vaarg.cpp index f0177906a09a81..82c32329502816 100644 --- a/clang/test/CodeGenCXX/x86_64-vaarg.cpp +++ b/clang/test/CodeGenCXX/x86_64-vaarg.cpp @@ -21,3 +21,18 @@ empty empty_record_test(int z, ...) { __builtin_va_start(list, z); return __builtin_va_arg(list, empty); } + +typedef struct { + struct{} a; + double b; +} s1; + +// CHECK-LABEL: define{{.*}} double @{{.*}}f +// CHECK: vaarg.in_reg: +// CHECK: vaarg.in_mem: +// CHECK: vaarg.end: +s1 f(int z, ...) { + __builtin_va_list list; + __builtin_va_start(list, z); + return __builtin_va_arg(list, s1); +} ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [X86_32] fix weird edge case in vaarg. (PR #86388)
https://github.com/CoTinker created https://github.com/llvm/llvm-project/pull/86388 struct SuperEmpty { struct{ int a[0];} b;}; Such 0 sized structs in c++ mode can not be ignored in i386 for that c++ fields are never empty.But when EmitVAArg, its size is 0, so that va_list not increase.Maybe we can use direct in this case. https://github.com/llvm/llvm-project/blob/691b97c884a15a7eac641ddf67c9f2f30fb4e747/clang/lib/CodeGen/ABIInfoImpl.cpp#L202-L216 This case use indirect before and `DirectSize == 0`, now we use direct and `DirectSize == 4`. Or we can just Ignore this kind of arguments, like X86_64 did. >From dda9d5ac87b05c71079b6ed3b5d4188ff22ce356 Mon Sep 17 00:00:00 2001 From: Longsheng Mou Date: Sat, 23 Mar 2024 17:53:58 +0800 Subject: [PATCH] [X86_32] fix weird edge case in vaarg. struct SuperEmpty { struct{ int a[0];} b;}; Such 0 sized structs in c++ mode can not be ignored in i386 for that c++ fields are never empty.But when EmitVAArg, its size is 0, so that va_list not increase.Maybe we can use direct in this case. --- clang/lib/CodeGen/Targets/X86.cpp | 3 +++ clang/test/CodeGenCXX/regparm.cpp | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/clang/lib/CodeGen/Targets/X86.cpp b/clang/lib/CodeGen/Targets/X86.cpp index 1ec0f159ebcb8a..8e6e7c17452048 100644 --- a/clang/lib/CodeGen/Targets/X86.cpp +++ b/clang/lib/CodeGen/Targets/X86.cpp @@ -805,6 +805,9 @@ ABIArgInfo X86_32ABIInfo::classifyArgumentType(QualType Ty, CCState &State, if (!IsWin32StructABI && isEmptyRecord(getContext(), Ty, true)) return ABIArgInfo::getIgnore(); +if (TI.Width == 0 && getContext().getLangOpts().CPlusPlus) + return ABIArgInfo::getDirect(); + llvm::LLVMContext &LLVMContext = getVMContext(); llvm::IntegerType *Int32 = llvm::Type::getInt32Ty(LLVMContext); bool NeedsPadding = false; diff --git a/clang/test/CodeGenCXX/regparm.cpp b/clang/test/CodeGenCXX/regparm.cpp index 1fd471c2d0727b..559702a84c99e1 100644 --- a/clang/test/CodeGenCXX/regparm.cpp +++ b/clang/test/CodeGenCXX/regparm.cpp @@ -32,7 +32,7 @@ struct S3 { } a; }; __attribute((regparm(2))) void foo4(S3 a, int b); -// CHECK: declare void @_Z4foo42S3i(ptr noundef byval(%struct.S3) align 4, i32 inreg noundef) +// CHECK: declare void @_Z4foo42S3i(%struct.anon, i32 inreg noundef) void bar3(S3 a, int b) { foo4(a, b); } ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [X86_32] fix weird edge case in vaarg. (PR #86388)
https://github.com/CoTinker edited https://github.com/llvm/llvm-project/pull/86388 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [X86_32] fix weird edge case in vaarg. (PR #86388)
https://github.com/CoTinker updated https://github.com/llvm/llvm-project/pull/86388 >From 8752d9019851bd231f1777d20391af60f0b4365c Mon Sep 17 00:00:00 2001 From: Longsheng Mou Date: Sat, 23 Mar 2024 17:53:58 +0800 Subject: [PATCH] [X86_32] fix 0 sized struct case in vaarg. struct SuperEmpty { struct{ int a[0];} b;}; Such 0 sized structs in c++ mode can not be ignored in i386 for that c++ fields are never empty.But when EmitVAArg, its size is 0, so that va_list not increase.Maybe we can use direct in this case. --- clang/lib/CodeGen/Targets/X86.cpp | 3 +++ clang/test/CodeGenCXX/regparm.cpp | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/clang/lib/CodeGen/Targets/X86.cpp b/clang/lib/CodeGen/Targets/X86.cpp index 1ec0f159ebcb8a..8e6e7c17452048 100644 --- a/clang/lib/CodeGen/Targets/X86.cpp +++ b/clang/lib/CodeGen/Targets/X86.cpp @@ -805,6 +805,9 @@ ABIArgInfo X86_32ABIInfo::classifyArgumentType(QualType Ty, CCState &State, if (!IsWin32StructABI && isEmptyRecord(getContext(), Ty, true)) return ABIArgInfo::getIgnore(); +if (TI.Width == 0 && getContext().getLangOpts().CPlusPlus) + return ABIArgInfo::getDirect(); + llvm::LLVMContext &LLVMContext = getVMContext(); llvm::IntegerType *Int32 = llvm::Type::getInt32Ty(LLVMContext); bool NeedsPadding = false; diff --git a/clang/test/CodeGenCXX/regparm.cpp b/clang/test/CodeGenCXX/regparm.cpp index 1fd471c2d0727b..559702a84c99e1 100644 --- a/clang/test/CodeGenCXX/regparm.cpp +++ b/clang/test/CodeGenCXX/regparm.cpp @@ -32,7 +32,7 @@ struct S3 { } a; }; __attribute((regparm(2))) void foo4(S3 a, int b); -// CHECK: declare void @_Z4foo42S3i(ptr noundef byval(%struct.S3) align 4, i32 inreg noundef) +// CHECK: declare void @_Z4foo42S3i(%struct.anon, i32 inreg noundef) void bar3(S3 a, int b) { foo4(a, b); } ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [X86_32] fix 0 sized struct case in vaarg. (PR #86388)
https://github.com/CoTinker edited https://github.com/llvm/llvm-project/pull/86388 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [X86_32] fix 0 sized struct case in vaarg. (PR #86388)
https://github.com/CoTinker edited https://github.com/llvm/llvm-project/pull/86388 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [X86_64] fix SSE type error in vaarg. (PR #86377)
https://github.com/CoTinker updated https://github.com/llvm/llvm-project/pull/86377 >From b494f2e7f59668678f95d4a739d810f6fd6944aa Mon Sep 17 00:00:00 2001 From: Longsheng Mou Date: Sat, 23 Mar 2024 11:52:04 +0800 Subject: [PATCH] [X86_64] fix SSE type error in vaarg. tweak the position of the ++neededSSE when Lo is NoClass and Hi is SSE. --- clang/lib/CodeGen/Targets/X86.cpp | 3 +- clang/test/CodeGen/X86/x86_64-vaarg.c | 69 ++ clang/test/CodeGenCXX/x86_64-vaarg.cpp | 50 +-- 3 files changed, 117 insertions(+), 5 deletions(-) create mode 100644 clang/test/CodeGen/X86/x86_64-vaarg.c diff --git a/clang/lib/CodeGen/Targets/X86.cpp b/clang/lib/CodeGen/Targets/X86.cpp index 1ec0f159ebcb8a..6931768147a9b2 100644 --- a/clang/lib/CodeGen/Targets/X86.cpp +++ b/clang/lib/CodeGen/Targets/X86.cpp @@ -2788,12 +2788,11 @@ X86_64ABIInfo::classifyArgumentType(QualType Ty, unsigned freeIntRegs, // memory), except in situations involving unions. case X87Up: case SSE: +++neededSSE; HighPart = GetSSETypeAtOffset(CGT.ConvertType(Ty), 8, Ty, 8); if (Lo == NoClass) // Pass HighPart at offset 8 in memory. return ABIArgInfo::getDirect(HighPart, 8); - -++neededSSE; break; // AMD64-ABI 3.2.3p3: Rule 4. If the class is SSEUP, the diff --git a/clang/test/CodeGen/X86/x86_64-vaarg.c b/clang/test/CodeGen/X86/x86_64-vaarg.c new file mode 100644 index 00..a18ba836423881 --- /dev/null +++ b/clang/test/CodeGen/X86/x86_64-vaarg.c @@ -0,0 +1,69 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 4 +// RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm -o - %s | FileCheck %s + + +typedef struct { struct {} a; } empty; + +// CHECK-LABEL: define dso_local void @empty_record_test( +// CHECK-SAME: i32 noundef [[Z:%.*]], ...) #[[ATTR0:[0-9]+]] { +// CHECK-NEXT: entry: +// CHECK-NEXT:[[RETVAL:%.*]] = alloca [[STRUCT_EMPTY:%.*]], align 1 +// CHECK-NEXT:[[Z_ADDR:%.*]] = alloca i32, align 4 +// CHECK-NEXT:[[LIST:%.*]] = alloca [1 x %struct.__va_list_tag], align 16 +// CHECK-NEXT:[[TMP:%.*]] = alloca [[STRUCT_EMPTY]], align 1 +// CHECK-NEXT:store i32 [[Z]], ptr [[Z_ADDR]], align 4 +// CHECK-NEXT:[[ARRAYDECAY:%.*]] = getelementptr inbounds [1 x %struct.__va_list_tag], ptr [[LIST]], i64 0, i64 0 +// CHECK-NEXT:call void @llvm.va_start(ptr [[ARRAYDECAY]]) +// CHECK-NEXT:[[ARRAYDECAY1:%.*]] = getelementptr inbounds [1 x %struct.__va_list_tag], ptr [[LIST]], i64 0, i64 0 +// CHECK-NEXT:call void @llvm.memcpy.p0.p0.i64(ptr align 1 [[RETVAL]], ptr align 1 [[TMP]], i64 0, i1 false) +// CHECK-NEXT:ret void +// +empty empty_record_test(int z, ...) { + __builtin_va_list list; + __builtin_va_start(list, z); + return __builtin_va_arg(list, empty); +} + +typedef struct { + struct{} a; + double b; +} s1; + +// CHECK-LABEL: define dso_local double @f( +// CHECK-SAME: i32 noundef [[Z:%.*]], ...) #[[ATTR0]] { +// CHECK-NEXT: entry: +// CHECK-NEXT:[[RETVAL:%.*]] = alloca [[STRUCT_S1:%.*]], align 8 +// CHECK-NEXT:[[Z_ADDR:%.*]] = alloca i32, align 4 +// CHECK-NEXT:[[LIST:%.*]] = alloca [1 x %struct.__va_list_tag], align 16 +// CHECK-NEXT:store i32 [[Z]], ptr [[Z_ADDR]], align 4 +// CHECK-NEXT:[[ARRAYDECAY:%.*]] = getelementptr inbounds [1 x %struct.__va_list_tag], ptr [[LIST]], i64 0, i64 0 +// CHECK-NEXT:call void @llvm.va_start(ptr [[ARRAYDECAY]]) +// CHECK-NEXT:[[ARRAYDECAY1:%.*]] = getelementptr inbounds [1 x %struct.__va_list_tag], ptr [[LIST]], i64 0, i64 0 +// CHECK-NEXT:[[FP_OFFSET_P:%.*]] = getelementptr inbounds [[STRUCT___VA_LIST_TAG:%.*]], ptr [[ARRAYDECAY1]], i32 0, i32 1 +// CHECK-NEXT:[[FP_OFFSET:%.*]] = load i32, ptr [[FP_OFFSET_P]], align 4 +// CHECK-NEXT:[[FITS_IN_FP:%.*]] = icmp ule i32 [[FP_OFFSET]], 160 +// CHECK-NEXT:br i1 [[FITS_IN_FP]], label [[VAARG_IN_REG:%.*]], label [[VAARG_IN_MEM:%.*]] +// CHECK: vaarg.in_reg: +// CHECK-NEXT:[[TMP0:%.*]] = getelementptr inbounds [[STRUCT___VA_LIST_TAG]], ptr [[ARRAYDECAY1]], i32 0, i32 3 +// CHECK-NEXT:[[REG_SAVE_AREA:%.*]] = load ptr, ptr [[TMP0]], align 16 +// CHECK-NEXT:[[TMP1:%.*]] = getelementptr i8, ptr [[REG_SAVE_AREA]], i32 [[FP_OFFSET]] +// CHECK-NEXT:[[TMP2:%.*]] = add i32 [[FP_OFFSET]], 16 +// CHECK-NEXT:store i32 [[TMP2]], ptr [[FP_OFFSET_P]], align 4 +// CHECK-NEXT:br label [[VAARG_END:%.*]] +// CHECK: vaarg.in_mem: +// CHECK-NEXT:[[OVERFLOW_ARG_AREA_P:%.*]] = getelementptr inbounds [[STRUCT___VA_LIST_TAG]], ptr [[ARRAYDECAY1]], i32 0, i32 2 +// CHECK-NEXT:[[OVERFLOW_ARG_AREA:%.*]] = load ptr, ptr [[OVERFLOW_ARG_AREA_P]], align 8 +// CHECK-NEXT:[[OVERFLOW_ARG_AREA_NEXT:%.*]] = getelementptr i8, ptr [[OVERFLOW_ARG_AREA]], i32 8 +// CHECK-NEXT:store ptr [[OVERFLOW_ARG_AREA_NEXT]], ptr [[OVERFLOW_ARG_AREA_P]], align 8 +// CHECK-NEXT:br label [[VAARG_END]] +// CHECK: v
[clang] [X86_64] fix SSE type error in vaarg. (PR #86377)
@@ -21,3 +21,18 @@ empty empty_record_test(int z, ...) { __builtin_va_start(list, z); return __builtin_va_arg(list, empty); } + CoTinker wrote: done https://github.com/llvm/llvm-project/pull/86377 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [X86_32][C++] fix 0 sized struct case in vaarg. (PR #86388)
https://github.com/CoTinker edited https://github.com/llvm/llvm-project/pull/86388 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [X86_64] fix arg pass error in struct. (PR #85394)
https://github.com/CoTinker updated https://github.com/llvm/llvm-project/pull/85394 >From ad805988f682030cd3ed6ff6b063488ed6f5707c Mon Sep 17 00:00:00 2001 From: Longsheng Mou Date: Fri, 15 Mar 2024 20:50:54 +0800 Subject: [PATCH] [X86_64] fix arg pass error in struct. 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. --- clang/lib/CodeGen/Targets/X86.cpp | 6 +- clang/test/CodeGen/X86/x86_64-arguments.c | 18 ++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/clang/lib/CodeGen/Targets/X86.cpp b/clang/lib/CodeGen/Targets/X86.cpp index 2291c991fb1107..de0dfe32a54d3a 100644 --- a/clang/lib/CodeGen/Targets/X86.cpp +++ b/clang/lib/CodeGen/Targets/X86.cpp @@ -2100,8 +2100,12 @@ void X86_64ABIInfo::classify(QualType Ty, uint64_t OffsetBase, Class &Lo, postMerge(Size, Lo, Hi); return; } + + bool InMemory = Offset % getContext().getTypeAlign(i->getType()) || + (i->getType()->getAs() && + Offset % getContext().getTypeSize(i->getType())); // Note, skip this test for bit-fields, see below. - if (!BitField && Offset % getContext().getTypeAlign(i->getType())) { + if (!BitField && InMemory) { Lo = Memory; postMerge(Size, Lo, Hi); return; diff --git a/clang/test/CodeGen/X86/x86_64-arguments.c b/clang/test/CodeGen/X86/x86_64-arguments.c index cf5636cfd518b6..82845f0a2b31fd 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(ptr noundef byval(%struct.s67) align 8 %x) +void f67(struct s67 x) { +} + +typedef double t68 __attribute__((aligned (4))); +struct s68 { + int a; + t68 b; +}; +// CHECK-LABEL: define{{.*}} void @f68(ptr noundef byval(%struct.s68) align 8 %x) +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: ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [X86_64] fix arg pass error in struct. (PR #85394)
https://github.com/CoTinker closed https://github.com/llvm/llvm-project/pull/85394 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [X86_64] fix arg pass error in struct. (PR #86902)
https://github.com/CoTinker created https://github.com/llvm/llvm-project/pull/86902 ``` typedef long long t67 __attribute__((aligned (4))); struct s67 { int a; t67 b; }; void f67(struct s67 x) { } ``` When classify: a: Lo = Integer, Hi = NoClass b: Lo = Integer, Hi = NoClass struct S: Lo = Integer, Hi = NoClass ``` define dso_local void @f67(i64 %x.coerce) { ``` 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 https://github.com/llvm/llvm-project/issues/85387. >From ad805988f682030cd3ed6ff6b063488ed6f5707c Mon Sep 17 00:00:00 2001 From: Longsheng Mou Date: Fri, 15 Mar 2024 20:50:54 +0800 Subject: [PATCH] [X86_64] fix arg pass error in struct. 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. --- clang/lib/CodeGen/Targets/X86.cpp | 6 +- clang/test/CodeGen/X86/x86_64-arguments.c | 18 ++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/clang/lib/CodeGen/Targets/X86.cpp b/clang/lib/CodeGen/Targets/X86.cpp index 2291c991fb1107..de0dfe32a54d3a 100644 --- a/clang/lib/CodeGen/Targets/X86.cpp +++ b/clang/lib/CodeGen/Targets/X86.cpp @@ -2100,8 +2100,12 @@ void X86_64ABIInfo::classify(QualType Ty, uint64_t OffsetBase, Class &Lo, postMerge(Size, Lo, Hi); return; } + + bool InMemory = Offset % getContext().getTypeAlign(i->getType()) || + (i->getType()->getAs() && + Offset % getContext().getTypeSize(i->getType())); // Note, skip this test for bit-fields, see below. - if (!BitField && Offset % getContext().getTypeAlign(i->getType())) { + if (!BitField && InMemory) { Lo = Memory; postMerge(Size, Lo, Hi); return; diff --git a/clang/test/CodeGen/X86/x86_64-arguments.c b/clang/test/CodeGen/X86/x86_64-arguments.c index cf5636cfd518b6..82845f0a2b31fd 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(ptr noundef byval(%struct.s67) align 8 %x) +void f67(struct s67 x) { +} + +typedef double t68 __attribute__((aligned (4))); +struct s68 { + int a; + t68 b; +}; +// CHECK-LABEL: define{{.*}} void @f68(ptr noundef byval(%struct.s68) align 8 %x) +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: ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [X86_64] fix arg pass error in struct. (PR #86902)
CoTinker wrote: @DavidSpickett why my buildkite always fail, while check-all success in local environment. Could you please take a look at it? https://github.com/llvm/llvm-project/pull/86902 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [X86_32] Teach X86_32 va_arg to ignore empty structs. (PR #86075)
https://github.com/CoTinker updated https://github.com/llvm/llvm-project/pull/86075 >From 5178a001cc3ce765e3d29e91e24597fa1b0f42d6 Mon Sep 17 00:00:00 2001 From: Longsheng Mou Date: Thu, 21 Mar 2024 11:23:56 +0800 Subject: [PATCH] [X86_32] Teach X86_32 va_arg to ignore empty structs. Empty structs are ignored for parameter passing purposes, but va_arg was incrementing the pointer anyway for that the size of empty struct in c++ is 1 byte, which could lead to va_list getting out of sync. --- clang/lib/CodeGen/Targets/X86.cpp | 6 ++ clang/test/CodeGenCXX/x86_32-vaarg.cpp | 20 2 files changed, 26 insertions(+) create mode 100644 clang/test/CodeGenCXX/x86_32-vaarg.cpp diff --git a/clang/lib/CodeGen/Targets/X86.cpp b/clang/lib/CodeGen/Targets/X86.cpp index 1ec0f159ebcb8a..2cb880752de3ea 100644 --- a/clang/lib/CodeGen/Targets/X86.cpp +++ b/clang/lib/CodeGen/Targets/X86.cpp @@ -1069,6 +1069,12 @@ Address X86_32ABIInfo::EmitVAArg(CodeGenFunction &CGF, auto TypeInfo = getContext().getTypeInfoInChars(Ty); + CCState State(*const_cast(CGF.CurFnInfo)); + ABIArgInfo AI = classifyArgumentType(Ty, State, /*ArgIndex*/ 0); + // Empty records are ignored for parameter passing purposes. + if (AI.isIgnore()) +return CGF.CreateMemTemp(Ty); + // x86-32 changes the alignment of certain arguments on the stack. // // Just messing with TypeInfo like this works because we never pass diff --git a/clang/test/CodeGenCXX/x86_32-vaarg.cpp b/clang/test/CodeGenCXX/x86_32-vaarg.cpp new file mode 100644 index 00..23eac1164118c6 --- /dev/null +++ b/clang/test/CodeGenCXX/x86_32-vaarg.cpp @@ -0,0 +1,20 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py +// RUN: %clang_cc1 -triple i386-linux-gnu -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -triple i386-linux-gnu -emit-llvm -x c -o - %s | FileCheck %s + +typedef struct {} empty; + +// CHECK-LABEL: @{{.*}}empty_record_test +// CHECK-NEXT: entry: +// CHECK-NEXT:[[RESULT_PTR:%.*]] = alloca ptr, align 4 +// CHECK-NEXT:[[Z_ADDR:%.*]] = alloca i32, align 4 +// CHECK-NEXT:[[LIST:%.*]] = alloca ptr, align 4 +// CHECK-NEXT:[[TMP:%.*]] = alloca [[STRUCT_EMPTY:%.*]], align 1 +// CHECK-NEXT:store ptr [[AGG_RESULT:%.*]], ptr [[RESULT_PTR]], align 4 +// CHECK-NEXT:store i32 [[Z:%.*]], ptr [[Z_ADDR]], align 4 +// CHECK-NEXT:call void @llvm.va_start(ptr [[LIST]]) +empty empty_record_test(int z, ...) { + __builtin_va_list list; + __builtin_va_start(list, z); + return __builtin_va_arg(list, empty); +} ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [X86_32] Teach X86_32 va_arg to ignore empty structs. (PR #86075)
https://github.com/CoTinker updated https://github.com/llvm/llvm-project/pull/86075 >From 929fba43012209b74b654b8d9a017a43826063fe Mon Sep 17 00:00:00 2001 From: Longsheng Mou Date: Thu, 21 Mar 2024 11:23:56 +0800 Subject: [PATCH] [X86_32] Teach X86_32 va_arg to ignore empty structs. Empty structs are ignored for parameter passing purposes, but va_arg was incrementing the pointer anyway for that the size of empty struct in c++ is 1 byte, which could lead to va_list getting out of sync. --- clang/lib/CodeGen/Targets/X86.cpp | 6 ++ clang/test/CodeGenCXX/x86_32-vaarg.cpp | 20 2 files changed, 26 insertions(+) create mode 100644 clang/test/CodeGenCXX/x86_32-vaarg.cpp diff --git a/clang/lib/CodeGen/Targets/X86.cpp b/clang/lib/CodeGen/Targets/X86.cpp index 1ec0f159ebcb8a..38143d1eed21aa 100644 --- a/clang/lib/CodeGen/Targets/X86.cpp +++ b/clang/lib/CodeGen/Targets/X86.cpp @@ -1069,6 +1069,12 @@ Address X86_32ABIInfo::EmitVAArg(CodeGenFunction &CGF, auto TypeInfo = getContext().getTypeInfoInChars(Ty); + CCState State(*const_cast(CGF.CurFnInfo)); + ABIArgInfo AI = classifyArgumentType(Ty, State, /*ArgIndex*/ 0); + // Empty records are ignored for parameter passing purposes. + if (AI.isIgnore()) +return CGF.CreateMemTemp(Ty); + // x86-32 changes the alignment of certain arguments on the stack. // // Just messing with TypeInfo like this works because we never pass diff --git a/clang/test/CodeGenCXX/x86_32-vaarg.cpp b/clang/test/CodeGenCXX/x86_32-vaarg.cpp new file mode 100644 index 00..23eac1164118c6 --- /dev/null +++ b/clang/test/CodeGenCXX/x86_32-vaarg.cpp @@ -0,0 +1,20 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py +// RUN: %clang_cc1 -triple i386-linux-gnu -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -triple i386-linux-gnu -emit-llvm -x c -o - %s | FileCheck %s + +typedef struct {} empty; + +// CHECK-LABEL: @{{.*}}empty_record_test +// CHECK-NEXT: entry: +// CHECK-NEXT:[[RESULT_PTR:%.*]] = alloca ptr, align 4 +// CHECK-NEXT:[[Z_ADDR:%.*]] = alloca i32, align 4 +// CHECK-NEXT:[[LIST:%.*]] = alloca ptr, align 4 +// CHECK-NEXT:[[TMP:%.*]] = alloca [[STRUCT_EMPTY:%.*]], align 1 +// CHECK-NEXT:store ptr [[AGG_RESULT:%.*]], ptr [[RESULT_PTR]], align 4 +// CHECK-NEXT:store i32 [[Z:%.*]], ptr [[Z_ADDR]], align 4 +// CHECK-NEXT:call void @llvm.va_start(ptr [[LIST]]) +empty empty_record_test(int z, ...) { + __builtin_va_list list; + __builtin_va_start(list, z); + return __builtin_va_arg(list, empty); +} ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [X86_32] Teach X86_32 va_arg to ignore empty structs. (PR #86075)
https://github.com/CoTinker updated https://github.com/llvm/llvm-project/pull/86075 >From a4d9a6fefdbe7c0ee6a891af230438a10ddd7c5a Mon Sep 17 00:00:00 2001 From: Longsheng Mou Date: Thu, 21 Mar 2024 11:23:56 +0800 Subject: [PATCH] [X86_32] Teach X86_32 va_arg to ignore empty structs. Empty structs are ignored for parameter passing purposes, but va_arg was incrementing the pointer anyway for that the size of empty struct in c++ is 1 byte, which could lead to va_list getting out of sync. --- clang/lib/CodeGen/Targets/X86.cpp | 6 ++ clang/test/CodeGenCXX/x86_32-vaarg.cpp | 20 2 files changed, 26 insertions(+) create mode 100644 clang/test/CodeGenCXX/x86_32-vaarg.cpp diff --git a/clang/lib/CodeGen/Targets/X86.cpp b/clang/lib/CodeGen/Targets/X86.cpp index 1146a851a7715d..c831777699f627 100644 --- a/clang/lib/CodeGen/Targets/X86.cpp +++ b/clang/lib/CodeGen/Targets/X86.cpp @@ -1069,6 +1069,12 @@ Address X86_32ABIInfo::EmitVAArg(CodeGenFunction &CGF, auto TypeInfo = getContext().getTypeInfoInChars(Ty); + CCState State(*const_cast(CGF.CurFnInfo)); + ABIArgInfo AI = classifyArgumentType(Ty, State, /*ArgIndex*/ 0); + // Empty records are ignored for parameter passing purposes. + if (AI.isIgnore()) +return CGF.CreateMemTemp(Ty); + // x86-32 changes the alignment of certain arguments on the stack. // // Just messing with TypeInfo like this works because we never pass diff --git a/clang/test/CodeGenCXX/x86_32-vaarg.cpp b/clang/test/CodeGenCXX/x86_32-vaarg.cpp new file mode 100644 index 00..23eac1164118c6 --- /dev/null +++ b/clang/test/CodeGenCXX/x86_32-vaarg.cpp @@ -0,0 +1,20 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py +// RUN: %clang_cc1 -triple i386-linux-gnu -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -triple i386-linux-gnu -emit-llvm -x c -o - %s | FileCheck %s + +typedef struct {} empty; + +// CHECK-LABEL: @{{.*}}empty_record_test +// CHECK-NEXT: entry: +// CHECK-NEXT:[[RESULT_PTR:%.*]] = alloca ptr, align 4 +// CHECK-NEXT:[[Z_ADDR:%.*]] = alloca i32, align 4 +// CHECK-NEXT:[[LIST:%.*]] = alloca ptr, align 4 +// CHECK-NEXT:[[TMP:%.*]] = alloca [[STRUCT_EMPTY:%.*]], align 1 +// CHECK-NEXT:store ptr [[AGG_RESULT:%.*]], ptr [[RESULT_PTR]], align 4 +// CHECK-NEXT:store i32 [[Z:%.*]], ptr [[Z_ADDR]], align 4 +// CHECK-NEXT:call void @llvm.va_start(ptr [[LIST]]) +empty empty_record_test(int z, ...) { + __builtin_va_list list; + __builtin_va_start(list, z); + return __builtin_va_arg(list, empty); +} ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [X86_64] fix arg pass error in struct. (PR #86902)
https://github.com/CoTinker updated https://github.com/llvm/llvm-project/pull/86902 >From 09596bbeeedecb312f8be40d153bb267abc2d659 Mon Sep 17 00:00:00 2001 From: Longsheng Mou Date: Fri, 15 Mar 2024 20:50:54 +0800 Subject: [PATCH] [X86_64] fix arg pass error in struct. 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. --- clang/lib/CodeGen/Targets/X86.cpp | 6 +- clang/test/CodeGen/X86/x86_64-arguments.c | 18 ++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/clang/lib/CodeGen/Targets/X86.cpp b/clang/lib/CodeGen/Targets/X86.cpp index 1146a851a7715d..8f4df98af117a0 100644 --- a/clang/lib/CodeGen/Targets/X86.cpp +++ b/clang/lib/CodeGen/Targets/X86.cpp @@ -2100,8 +2100,12 @@ void X86_64ABIInfo::classify(QualType Ty, uint64_t OffsetBase, Class &Lo, postMerge(Size, Lo, Hi); return; } + + bool InMemory = Offset % getContext().getTypeAlign(i->getType()) || + (i->getType()->getAs() && + Offset % getContext().getTypeSize(i->getType())); // Note, skip this test for bit-fields, see below. - if (!BitField && Offset % getContext().getTypeAlign(i->getType())) { + if (!BitField && InMemory) { Lo = Memory; postMerge(Size, Lo, Hi); return; diff --git a/clang/test/CodeGen/X86/x86_64-arguments.c b/clang/test/CodeGen/X86/x86_64-arguments.c index cf5636cfd518b6..82845f0a2b31fd 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(ptr noundef byval(%struct.s67) align 8 %x) +void f67(struct s67 x) { +} + +typedef double t68 __attribute__((aligned (4))); +struct s68 { + int a; + t68 b; +}; +// CHECK-LABEL: define{{.*}} void @f68(ptr noundef byval(%struct.s68) align 8 %x) +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: ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [X86_64] fix arg pass error in struct. (PR #86902)
CoTinker wrote: Thank you very much, I'll try it. https://github.com/llvm/llvm-project/pull/86902 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [X86_32] Teach X86_32 va_arg to ignore empty structs. (PR #86075)
https://github.com/CoTinker updated https://github.com/llvm/llvm-project/pull/86075 >From 355f540288d87ca35a8e5790e4eaff383d619201 Mon Sep 17 00:00:00 2001 From: Longsheng Mou Date: Thu, 21 Mar 2024 11:23:56 +0800 Subject: [PATCH] [X86_32] Teach X86_32 va_arg to ignore empty structs. Empty structs are ignored for parameter passing purposes, but va_arg was incrementing the pointer anyway for that the size of empty struct in c++ is 1 byte, which could lead to va_list getting out of sync. --- clang/lib/CodeGen/Targets/X86.cpp | 6 ++ clang/test/CodeGenCXX/x86_32-vaarg.cpp | 20 2 files changed, 26 insertions(+) create mode 100644 clang/test/CodeGenCXX/x86_32-vaarg.cpp diff --git a/clang/lib/CodeGen/Targets/X86.cpp b/clang/lib/CodeGen/Targets/X86.cpp index 1146a851a7715d..c831777699f627 100644 --- a/clang/lib/CodeGen/Targets/X86.cpp +++ b/clang/lib/CodeGen/Targets/X86.cpp @@ -1069,6 +1069,12 @@ Address X86_32ABIInfo::EmitVAArg(CodeGenFunction &CGF, auto TypeInfo = getContext().getTypeInfoInChars(Ty); + CCState State(*const_cast(CGF.CurFnInfo)); + ABIArgInfo AI = classifyArgumentType(Ty, State, /*ArgIndex*/ 0); + // Empty records are ignored for parameter passing purposes. + if (AI.isIgnore()) +return CGF.CreateMemTemp(Ty); + // x86-32 changes the alignment of certain arguments on the stack. // // Just messing with TypeInfo like this works because we never pass diff --git a/clang/test/CodeGenCXX/x86_32-vaarg.cpp b/clang/test/CodeGenCXX/x86_32-vaarg.cpp new file mode 100644 index 00..23eac1164118c6 --- /dev/null +++ b/clang/test/CodeGenCXX/x86_32-vaarg.cpp @@ -0,0 +1,20 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py +// RUN: %clang_cc1 -triple i386-linux-gnu -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -triple i386-linux-gnu -emit-llvm -x c -o - %s | FileCheck %s + +typedef struct {} empty; + +// CHECK-LABEL: @{{.*}}empty_record_test +// CHECK-NEXT: entry: +// CHECK-NEXT:[[RESULT_PTR:%.*]] = alloca ptr, align 4 +// CHECK-NEXT:[[Z_ADDR:%.*]] = alloca i32, align 4 +// CHECK-NEXT:[[LIST:%.*]] = alloca ptr, align 4 +// CHECK-NEXT:[[TMP:%.*]] = alloca [[STRUCT_EMPTY:%.*]], align 1 +// CHECK-NEXT:store ptr [[AGG_RESULT:%.*]], ptr [[RESULT_PTR]], align 4 +// CHECK-NEXT:store i32 [[Z:%.*]], ptr [[Z_ADDR]], align 4 +// CHECK-NEXT:call void @llvm.va_start(ptr [[LIST]]) +empty empty_record_test(int z, ...) { + __builtin_va_list list; + __builtin_va_start(list, z); + return __builtin_va_arg(list, empty); +} ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [X86_32] Teach X86_32 va_arg to ignore empty structs. (PR #86075)
https://github.com/CoTinker updated https://github.com/llvm/llvm-project/pull/86075 >From 95a11789d89a57cc96512bd180949164f89695d0 Mon Sep 17 00:00:00 2001 From: Longsheng Mou Date: Thu, 21 Mar 2024 11:23:56 +0800 Subject: [PATCH] [X86_32] Teach X86_32 va_arg to ignore empty structs. Empty structs are ignored for parameter passing purposes, but va_arg was incrementing the pointer anyway for that the size of empty struct in c++ is 1 byte, which could lead to va_list getting out of sync. --- clang/lib/CodeGen/Targets/X86.cpp | 6 ++ clang/test/CodeGenCXX/x86_32-vaarg.cpp | 20 2 files changed, 26 insertions(+) create mode 100644 clang/test/CodeGenCXX/x86_32-vaarg.cpp diff --git a/clang/lib/CodeGen/Targets/X86.cpp b/clang/lib/CodeGen/Targets/X86.cpp index 1146a851a7715d..c831777699f627 100644 --- a/clang/lib/CodeGen/Targets/X86.cpp +++ b/clang/lib/CodeGen/Targets/X86.cpp @@ -1069,6 +1069,12 @@ Address X86_32ABIInfo::EmitVAArg(CodeGenFunction &CGF, auto TypeInfo = getContext().getTypeInfoInChars(Ty); + CCState State(*const_cast(CGF.CurFnInfo)); + ABIArgInfo AI = classifyArgumentType(Ty, State, /*ArgIndex*/ 0); + // Empty records are ignored for parameter passing purposes. + if (AI.isIgnore()) +return CGF.CreateMemTemp(Ty); + // x86-32 changes the alignment of certain arguments on the stack. // // Just messing with TypeInfo like this works because we never pass diff --git a/clang/test/CodeGenCXX/x86_32-vaarg.cpp b/clang/test/CodeGenCXX/x86_32-vaarg.cpp new file mode 100644 index 00..23eac1164118c6 --- /dev/null +++ b/clang/test/CodeGenCXX/x86_32-vaarg.cpp @@ -0,0 +1,20 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py +// RUN: %clang_cc1 -triple i386-linux-gnu -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -triple i386-linux-gnu -emit-llvm -x c -o - %s | FileCheck %s + +typedef struct {} empty; + +// CHECK-LABEL: @{{.*}}empty_record_test +// CHECK-NEXT: entry: +// CHECK-NEXT:[[RESULT_PTR:%.*]] = alloca ptr, align 4 +// CHECK-NEXT:[[Z_ADDR:%.*]] = alloca i32, align 4 +// CHECK-NEXT:[[LIST:%.*]] = alloca ptr, align 4 +// CHECK-NEXT:[[TMP:%.*]] = alloca [[STRUCT_EMPTY:%.*]], align 1 +// CHECK-NEXT:store ptr [[AGG_RESULT:%.*]], ptr [[RESULT_PTR]], align 4 +// CHECK-NEXT:store i32 [[Z:%.*]], ptr [[Z_ADDR]], align 4 +// CHECK-NEXT:call void @llvm.va_start(ptr [[LIST]]) +empty empty_record_test(int z, ...) { + __builtin_va_list list; + __builtin_va_start(list, z); + return __builtin_va_arg(list, empty); +} ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [X86_32] Teach X86_32 va_arg to ignore empty structs. (PR #86075)
https://github.com/CoTinker updated https://github.com/llvm/llvm-project/pull/86075 >From 85d829dcef3484892d6db8f6a0329cb9bc34c349 Mon Sep 17 00:00:00 2001 From: Longsheng Mou Date: Thu, 21 Mar 2024 11:23:56 +0800 Subject: [PATCH] [X86_32] Teach X86_32 va_arg to ignore empty structs. Empty structs are ignored for parameter passing purposes, but va_arg was incrementing the pointer anyway for that the size of empty struct in c++ is 1 byte, which could lead to va_list getting out of sync. --- clang/lib/CodeGen/Targets/X86.cpp | 6 ++ clang/test/CodeGenCXX/x86_32-vaarg.cpp | 21 + 2 files changed, 27 insertions(+) create mode 100644 clang/test/CodeGenCXX/x86_32-vaarg.cpp diff --git a/clang/lib/CodeGen/Targets/X86.cpp b/clang/lib/CodeGen/Targets/X86.cpp index 1146a851a7715d..c831777699f627 100644 --- a/clang/lib/CodeGen/Targets/X86.cpp +++ b/clang/lib/CodeGen/Targets/X86.cpp @@ -1069,6 +1069,12 @@ Address X86_32ABIInfo::EmitVAArg(CodeGenFunction &CGF, auto TypeInfo = getContext().getTypeInfoInChars(Ty); + CCState State(*const_cast(CGF.CurFnInfo)); + ABIArgInfo AI = classifyArgumentType(Ty, State, /*ArgIndex*/ 0); + // Empty records are ignored for parameter passing purposes. + if (AI.isIgnore()) +return CGF.CreateMemTemp(Ty); + // x86-32 changes the alignment of certain arguments on the stack. // // Just messing with TypeInfo like this works because we never pass diff --git a/clang/test/CodeGenCXX/x86_32-vaarg.cpp b/clang/test/CodeGenCXX/x86_32-vaarg.cpp new file mode 100644 index 00..dcc2f7f96a40f1 --- /dev/null +++ b/clang/test/CodeGenCXX/x86_32-vaarg.cpp @@ -0,0 +1,21 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py +// RUN: %clang_cc1 -triple i386-linux-gnu -emit-llvm -o - %s | FileCheck %s + +typedef struct {} empty; + +// CHECK-LABEL: @_Z17empty_record_testiz( +// CHECK-NEXT: entry: +// CHECK-NEXT:[[RESULT_PTR:%.*]] = alloca ptr, align 4 +// CHECK-NEXT:[[Z_ADDR:%.*]] = alloca i32, align 4 +// CHECK-NEXT:[[LIST:%.*]] = alloca ptr, align 4 +// CHECK-NEXT:[[TMP:%.*]] = alloca [[STRUCT_EMPTY:%.*]], align 1 +// CHECK-NEXT:store ptr [[AGG_RESULT:%.*]], ptr [[RESULT_PTR]], align 4 +// CHECK-NEXT:store i32 [[Z:%.*]], ptr [[Z_ADDR]], align 4 +// CHECK-NEXT:call void @llvm.va_start.p0(ptr [[LIST]]) +// CHECK-NEXT:ret void +// +empty empty_record_test(int z, ...) { + __builtin_va_list list; + __builtin_va_start(list, z); + return __builtin_va_arg(list, empty); +} ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [X86_64] fix empty structure vaarg in c++ (PR #77907)
@@ -3014,6 +3014,16 @@ Address X86_64ABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, ABIArgInfo AI = classifyArgumentType(Ty, 0, neededInt, neededSSE, /*isNamedArg*/false); + // Empty records are ignored for parameter passing purposes. + if (AI.isIgnore()) { +CharUnits Align = CGF.getContext().getTypeAlignInChars(Ty); +VAListAddr = CGF.Builder.CreateStructGEP(VAListAddr, 2); +llvm::Value *Load = CGF.Builder.CreateLoad(VAListAddr); +llvm::Value *Offset = llvm::ConstantInt::get(CGF.Int32Ty, 0); +Load = CGF.Builder.CreateGEP(CGF.Int8Ty, Load, Offset); +return Address(Load, CGF.ConvertTypeForMem(Ty), Align); CoTinker wrote: how to create a temporary? https://github.com/llvm/llvm-project/pull/77907 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [X86_64] fix empty structure vaarg in c++ (PR #77907)
@@ -2989,6 +2989,11 @@ static Address EmitX86_64VAArgFromMemory(CodeGenFunction &CGF, // an 8 byte boundary. uint64_t SizeInBytes = (CGF.getContext().getTypeSize(Ty) + 7) / 8; + + if (isEmptyRecord(CGF.getContext(), Ty, true)) { +SizeInBytes = 0; + } + CoTinker wrote: done https://github.com/llvm/llvm-project/pull/77907 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [X86_64] fix empty structure vaarg in c++ (PR #77907)
CoTinker wrote: > I checked it locally, the patch doesn't fix the reported problem: > > ``` > $ clang pr77036.cpp && ./a.out > -nan > Fail > ``` isEmptyRecord return false here, I am checking it. https://github.com/llvm/llvm-project/pull/77907 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [X86_64] fix empty structure vaarg in c++ (PR #77907)
CoTinker wrote: > I checked it locally, the patch doesn't fix the reported problem: > > ``` > $ clang pr77036.cpp && ./a.out > -nan > Fail > ``` It seems that `struct S14{}` is empty record, but `struct S14 { union{}a;}` is not. https://github.com/llvm/llvm-project/pull/77907 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [X86_64] fix empty structure vaarg in c++ (PR #77907)
CoTinker wrote: I've revised it. Can you check it again? @phoebewang https://github.com/llvm/llvm-project/pull/77907 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [X86_64] Fix empty field error in vaarg of C++. (PR #101639)
https://github.com/CoTinker updated https://github.com/llvm/llvm-project/pull/101639 >From 328ae6052894eb45c4e7541dadf63a3a04540cda Mon Sep 17 00:00:00 2001 From: Longsheng Mou Date: Fri, 2 Aug 2024 16:36:31 +0800 Subject: [PATCH 1/2] [X86_64] Fix empty field error in vaarg of C++. Such struct types: ``` struct { struct{} a; long long b; }; stuct { struct{} a; double b; }; ``` For such structures, Lo is NoClass and Hi is Integer/SSE. And when this structure argument is passed, the high part is passed at offset 8 in memory. So we should do special handling for these types in EmitVAArg. --- clang/lib/CodeGen/Targets/X86.cpp | 38 +++-- clang/test/CodeGenCXX/x86_64-vaarg.cpp | 211 - 2 files changed, 231 insertions(+), 18 deletions(-) diff --git a/clang/lib/CodeGen/Targets/X86.cpp b/clang/lib/CodeGen/Targets/X86.cpp index 26ff4e4ac0a3b5..0347bd01f82ef3 100644 --- a/clang/lib/CodeGen/Targets/X86.cpp +++ b/clang/lib/CodeGen/Targets/X86.cpp @@ -3124,26 +3124,40 @@ RValue X86_64ABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, CGF.Builder.CreateStore(V, CGF.Builder.CreateStructGEP(Tmp, 1)); RegAddr = Tmp.withElementType(LTy); - } else if (neededInt) { -RegAddr = Address(CGF.Builder.CreateGEP(CGF.Int8Ty, RegSaveArea, gp_offset), - LTy, CharUnits::fromQuantity(8)); - + } else if (neededInt || neededSSE == 1) { // Copy to a temporary if necessary to ensure the appropriate alignment. auto TInfo = getContext().getTypeInfoInChars(Ty); uint64_t TySize = TInfo.Width.getQuantity(); CharUnits TyAlign = TInfo.Align; -// Copy into a temporary if the type is more aligned than the -// register save area. -if (TyAlign.getQuantity() > 8) { +llvm::Value *GpOrFpOffset = neededInt ? gp_offset : fp_offset; +uint64_t Alignment = neededInt ? 8 : 16; +if (auto Offset = AI.getDirectOffset()) { Address Tmp = CGF.CreateMemTemp(Ty); - CGF.Builder.CreateMemCpy(Tmp, RegAddr, TySize, false); - RegAddr = Tmp; + llvm::Type *TyHi = AI.getCoerceToType(); + llvm::Value *Addr = + CGF.Builder.CreateGEP(CGF.Int8Ty, RegSaveArea, GpOrFpOffset); + llvm::Value *Src = CGF.Builder.CreateAlignedLoad(TyHi, Addr, TyAlign); + llvm::Value *PtrOffset = llvm::ConstantInt::get(CGF.Int32Ty, Offset); + Address Dst = Address( + CGF.Builder.CreateGEP(CGF.Int8Ty, Tmp.getBasePointer(), PtrOffset), + LTy, TyAlign); + CGF.Builder.CreateStore(Src, Dst); + RegAddr = Tmp.withElementType(LTy); +} else { + RegAddr = + Address(CGF.Builder.CreateGEP(CGF.Int8Ty, RegSaveArea, GpOrFpOffset), + LTy, CharUnits::fromQuantity(Alignment)); + + // Copy into a temporary if the type is more aligned than the + // register save area. + if (neededInt && TyAlign.getQuantity() > 8) { +Address Tmp = CGF.CreateMemTemp(Ty); +CGF.Builder.CreateMemCpy(Tmp, RegAddr, TySize, false); +RegAddr = Tmp; + } } - } else if (neededSSE == 1) { -RegAddr = Address(CGF.Builder.CreateGEP(CGF.Int8Ty, RegSaveArea, fp_offset), - LTy, CharUnits::fromQuantity(16)); } else { assert(neededSSE == 2 && "Invalid number of needed registers!"); // SSE registers are spaced 16 bytes apart in the register save diff --git a/clang/test/CodeGenCXX/x86_64-vaarg.cpp b/clang/test/CodeGenCXX/x86_64-vaarg.cpp index c4616a97e20555..1703b74ad10a2f 100644 --- a/clang/test/CodeGenCXX/x86_64-vaarg.cpp +++ b/clang/test/CodeGenCXX/x86_64-vaarg.cpp @@ -29,6 +29,7 @@ typedef struct { // CHECK-NEXT:[[RETVAL:%.*]] = alloca [[STRUCT_S1:%.*]], align 8 // CHECK-NEXT:[[Z_ADDR:%.*]] = alloca i32, align 4 // CHECK-NEXT:[[LIST:%.*]] = alloca [1 x %struct.__va_list_tag], align 16 +// CHECK-NEXT:[[TMP:%.*]] = alloca [[STRUCT_S1]], align 8 // CHECK-NEXT:store i32 [[Z:%.*]], ptr [[Z_ADDR]], align 4 // CHECK-NEXT:[[ARRAYDECAY:%.*]] = getelementptr inbounds [1 x %struct.__va_list_tag], ptr [[LIST]], i64 0, i64 0 // CHECK-NEXT:call void @llvm.va_start.p0(ptr [[ARRAYDECAY]]) @@ -41,8 +42,11 @@ typedef struct { // CHECK-NEXT:[[TMP0:%.*]] = getelementptr inbounds [[STRUCT___VA_LIST_TAG]], ptr [[ARRAYDECAY1]], i32 0, i32 3 // CHECK-NEXT:[[REG_SAVE_AREA:%.*]] = load ptr, ptr [[TMP0]], align 16 // CHECK-NEXT:[[TMP1:%.*]] = getelementptr i8, ptr [[REG_SAVE_AREA]], i32 [[FP_OFFSET]] -// CHECK-NEXT:[[TMP2:%.*]] = add i32 [[FP_OFFSET]], 16 -// CHECK-NEXT:store i32 [[TMP2]], ptr [[FP_OFFSET_P]], align 4 +// CHECK-NEXT:[[TMP2:%.*]] = load double, ptr [[TMP1]], align 8 +// CHECK-NEXT:[[TMP3:%.*]] = getelementptr i8, ptr [[TMP]], i32 8 +// CHECK-NEXT:store double [[TMP2]], ptr [[TMP3]], align 8 +// CHECK-NEXT:[[TMP4:%.*]] = add i32 [[FP_OFFSET]], 16 +// CHECK-NEXT:store i32 [[TMP4]], ptr [[FP_OFFSET_P]], align 4 // CHECK-NEXT:br label [[VAARG_END:
[clang] [X86_64] Fix empty field error in vaarg of C++. (PR #101639)
@@ -3124,26 +3124,40 @@ RValue X86_64ABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, CGF.Builder.CreateStore(V, CGF.Builder.CreateStructGEP(Tmp, 1)); RegAddr = Tmp.withElementType(LTy); - } else if (neededInt) { -RegAddr = Address(CGF.Builder.CreateGEP(CGF.Int8Ty, RegSaveArea, gp_offset), - LTy, CharUnits::fromQuantity(8)); - + } else if (neededInt || neededSSE == 1) { // Copy to a temporary if necessary to ensure the appropriate alignment. auto TInfo = getContext().getTypeInfoInChars(Ty); uint64_t TySize = TInfo.Width.getQuantity(); CharUnits TyAlign = TInfo.Align; +llvm::Value *GpOrFpOffset = neededInt ? gp_offset : fp_offset; +uint64_t Alignment = neededInt ? 8 : 16; +if (auto Offset = AI.getDirectOffset()) { + Address Tmp = CGF.CreateMemTemp(Ty); + llvm::Type *TyHi = AI.getCoerceToType(); + llvm::Value *Addr = + CGF.Builder.CreateGEP(CGF.Int8Ty, RegSaveArea, GpOrFpOffset); + llvm::Value *Src = CGF.Builder.CreateAlignedLoad(TyHi, Addr, TyAlign); + llvm::Value *PtrOffset = llvm::ConstantInt::get(CGF.Int32Ty, Offset); + Address Dst = Address( + CGF.Builder.CreateGEP(CGF.Int8Ty, Tmp.getBasePointer(), PtrOffset), + LTy, TyAlign); + CGF.Builder.CreateStore(Src, Dst); + RegAddr = Tmp.withElementType(LTy); +} else { + RegAddr = + Address(CGF.Builder.CreateGEP(CGF.Int8Ty, RegSaveArea, GpOrFpOffset), + LTy, CharUnits::fromQuantity(Alignment)); +} + // Copy into a temporary if the type is more aligned than the // register save area. -if (TyAlign.getQuantity() > 8) { +if (neededInt && TyAlign.getQuantity() > 8) { CoTinker wrote: I am glad to fix it. https://github.com/llvm/llvm-project/pull/101639 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [X86_64] Fix empty field error in vaarg of C++. (PR #101639)
https://github.com/CoTinker updated https://github.com/llvm/llvm-project/pull/101639 >From 328ae6052894eb45c4e7541dadf63a3a04540cda Mon Sep 17 00:00:00 2001 From: Longsheng Mou Date: Fri, 2 Aug 2024 16:36:31 +0800 Subject: [PATCH 1/2] [X86_64] Fix empty field error in vaarg of C++. Such struct types: ``` struct { struct{} a; long long b; }; stuct { struct{} a; double b; }; ``` For such structures, Lo is NoClass and Hi is Integer/SSE. And when this structure argument is passed, the high part is passed at offset 8 in memory. So we should do special handling for these types in EmitVAArg. --- clang/lib/CodeGen/Targets/X86.cpp | 38 +++-- clang/test/CodeGenCXX/x86_64-vaarg.cpp | 211 - 2 files changed, 231 insertions(+), 18 deletions(-) diff --git a/clang/lib/CodeGen/Targets/X86.cpp b/clang/lib/CodeGen/Targets/X86.cpp index 26ff4e4ac0a3b5..0347bd01f82ef3 100644 --- a/clang/lib/CodeGen/Targets/X86.cpp +++ b/clang/lib/CodeGen/Targets/X86.cpp @@ -3124,26 +3124,40 @@ RValue X86_64ABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, CGF.Builder.CreateStore(V, CGF.Builder.CreateStructGEP(Tmp, 1)); RegAddr = Tmp.withElementType(LTy); - } else if (neededInt) { -RegAddr = Address(CGF.Builder.CreateGEP(CGF.Int8Ty, RegSaveArea, gp_offset), - LTy, CharUnits::fromQuantity(8)); - + } else if (neededInt || neededSSE == 1) { // Copy to a temporary if necessary to ensure the appropriate alignment. auto TInfo = getContext().getTypeInfoInChars(Ty); uint64_t TySize = TInfo.Width.getQuantity(); CharUnits TyAlign = TInfo.Align; -// Copy into a temporary if the type is more aligned than the -// register save area. -if (TyAlign.getQuantity() > 8) { +llvm::Value *GpOrFpOffset = neededInt ? gp_offset : fp_offset; +uint64_t Alignment = neededInt ? 8 : 16; +if (auto Offset = AI.getDirectOffset()) { Address Tmp = CGF.CreateMemTemp(Ty); - CGF.Builder.CreateMemCpy(Tmp, RegAddr, TySize, false); - RegAddr = Tmp; + llvm::Type *TyHi = AI.getCoerceToType(); + llvm::Value *Addr = + CGF.Builder.CreateGEP(CGF.Int8Ty, RegSaveArea, GpOrFpOffset); + llvm::Value *Src = CGF.Builder.CreateAlignedLoad(TyHi, Addr, TyAlign); + llvm::Value *PtrOffset = llvm::ConstantInt::get(CGF.Int32Ty, Offset); + Address Dst = Address( + CGF.Builder.CreateGEP(CGF.Int8Ty, Tmp.getBasePointer(), PtrOffset), + LTy, TyAlign); + CGF.Builder.CreateStore(Src, Dst); + RegAddr = Tmp.withElementType(LTy); +} else { + RegAddr = + Address(CGF.Builder.CreateGEP(CGF.Int8Ty, RegSaveArea, GpOrFpOffset), + LTy, CharUnits::fromQuantity(Alignment)); + + // Copy into a temporary if the type is more aligned than the + // register save area. + if (neededInt && TyAlign.getQuantity() > 8) { +Address Tmp = CGF.CreateMemTemp(Ty); +CGF.Builder.CreateMemCpy(Tmp, RegAddr, TySize, false); +RegAddr = Tmp; + } } - } else if (neededSSE == 1) { -RegAddr = Address(CGF.Builder.CreateGEP(CGF.Int8Ty, RegSaveArea, fp_offset), - LTy, CharUnits::fromQuantity(16)); } else { assert(neededSSE == 2 && "Invalid number of needed registers!"); // SSE registers are spaced 16 bytes apart in the register save diff --git a/clang/test/CodeGenCXX/x86_64-vaarg.cpp b/clang/test/CodeGenCXX/x86_64-vaarg.cpp index c4616a97e20555..1703b74ad10a2f 100644 --- a/clang/test/CodeGenCXX/x86_64-vaarg.cpp +++ b/clang/test/CodeGenCXX/x86_64-vaarg.cpp @@ -29,6 +29,7 @@ typedef struct { // CHECK-NEXT:[[RETVAL:%.*]] = alloca [[STRUCT_S1:%.*]], align 8 // CHECK-NEXT:[[Z_ADDR:%.*]] = alloca i32, align 4 // CHECK-NEXT:[[LIST:%.*]] = alloca [1 x %struct.__va_list_tag], align 16 +// CHECK-NEXT:[[TMP:%.*]] = alloca [[STRUCT_S1]], align 8 // CHECK-NEXT:store i32 [[Z:%.*]], ptr [[Z_ADDR]], align 4 // CHECK-NEXT:[[ARRAYDECAY:%.*]] = getelementptr inbounds [1 x %struct.__va_list_tag], ptr [[LIST]], i64 0, i64 0 // CHECK-NEXT:call void @llvm.va_start.p0(ptr [[ARRAYDECAY]]) @@ -41,8 +42,11 @@ typedef struct { // CHECK-NEXT:[[TMP0:%.*]] = getelementptr inbounds [[STRUCT___VA_LIST_TAG]], ptr [[ARRAYDECAY1]], i32 0, i32 3 // CHECK-NEXT:[[REG_SAVE_AREA:%.*]] = load ptr, ptr [[TMP0]], align 16 // CHECK-NEXT:[[TMP1:%.*]] = getelementptr i8, ptr [[REG_SAVE_AREA]], i32 [[FP_OFFSET]] -// CHECK-NEXT:[[TMP2:%.*]] = add i32 [[FP_OFFSET]], 16 -// CHECK-NEXT:store i32 [[TMP2]], ptr [[FP_OFFSET_P]], align 4 +// CHECK-NEXT:[[TMP2:%.*]] = load double, ptr [[TMP1]], align 8 +// CHECK-NEXT:[[TMP3:%.*]] = getelementptr i8, ptr [[TMP]], i32 8 +// CHECK-NEXT:store double [[TMP2]], ptr [[TMP3]], align 8 +// CHECK-NEXT:[[TMP4:%.*]] = add i32 [[FP_OFFSET]], 16 +// CHECK-NEXT:store i32 [[TMP4]], ptr [[FP_OFFSET_P]], align 4 // CHECK-NEXT:br label [[VAARG_END:
[clang] [X86_64] Fix empty field error in vaarg of C++. (PR #101639)
https://github.com/CoTinker updated https://github.com/llvm/llvm-project/pull/101639 >From 328ae6052894eb45c4e7541dadf63a3a04540cda Mon Sep 17 00:00:00 2001 From: Longsheng Mou Date: Fri, 2 Aug 2024 16:36:31 +0800 Subject: [PATCH 1/2] [X86_64] Fix empty field error in vaarg of C++. Such struct types: ``` struct { struct{} a; long long b; }; stuct { struct{} a; double b; }; ``` For such structures, Lo is NoClass and Hi is Integer/SSE. And when this structure argument is passed, the high part is passed at offset 8 in memory. So we should do special handling for these types in EmitVAArg. --- clang/lib/CodeGen/Targets/X86.cpp | 38 +++-- clang/test/CodeGenCXX/x86_64-vaarg.cpp | 211 - 2 files changed, 231 insertions(+), 18 deletions(-) diff --git a/clang/lib/CodeGen/Targets/X86.cpp b/clang/lib/CodeGen/Targets/X86.cpp index 26ff4e4ac0a3b5..0347bd01f82ef3 100644 --- a/clang/lib/CodeGen/Targets/X86.cpp +++ b/clang/lib/CodeGen/Targets/X86.cpp @@ -3124,26 +3124,40 @@ RValue X86_64ABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, CGF.Builder.CreateStore(V, CGF.Builder.CreateStructGEP(Tmp, 1)); RegAddr = Tmp.withElementType(LTy); - } else if (neededInt) { -RegAddr = Address(CGF.Builder.CreateGEP(CGF.Int8Ty, RegSaveArea, gp_offset), - LTy, CharUnits::fromQuantity(8)); - + } else if (neededInt || neededSSE == 1) { // Copy to a temporary if necessary to ensure the appropriate alignment. auto TInfo = getContext().getTypeInfoInChars(Ty); uint64_t TySize = TInfo.Width.getQuantity(); CharUnits TyAlign = TInfo.Align; -// Copy into a temporary if the type is more aligned than the -// register save area. -if (TyAlign.getQuantity() > 8) { +llvm::Value *GpOrFpOffset = neededInt ? gp_offset : fp_offset; +uint64_t Alignment = neededInt ? 8 : 16; +if (auto Offset = AI.getDirectOffset()) { Address Tmp = CGF.CreateMemTemp(Ty); - CGF.Builder.CreateMemCpy(Tmp, RegAddr, TySize, false); - RegAddr = Tmp; + llvm::Type *TyHi = AI.getCoerceToType(); + llvm::Value *Addr = + CGF.Builder.CreateGEP(CGF.Int8Ty, RegSaveArea, GpOrFpOffset); + llvm::Value *Src = CGF.Builder.CreateAlignedLoad(TyHi, Addr, TyAlign); + llvm::Value *PtrOffset = llvm::ConstantInt::get(CGF.Int32Ty, Offset); + Address Dst = Address( + CGF.Builder.CreateGEP(CGF.Int8Ty, Tmp.getBasePointer(), PtrOffset), + LTy, TyAlign); + CGF.Builder.CreateStore(Src, Dst); + RegAddr = Tmp.withElementType(LTy); +} else { + RegAddr = + Address(CGF.Builder.CreateGEP(CGF.Int8Ty, RegSaveArea, GpOrFpOffset), + LTy, CharUnits::fromQuantity(Alignment)); + + // Copy into a temporary if the type is more aligned than the + // register save area. + if (neededInt && TyAlign.getQuantity() > 8) { +Address Tmp = CGF.CreateMemTemp(Ty); +CGF.Builder.CreateMemCpy(Tmp, RegAddr, TySize, false); +RegAddr = Tmp; + } } - } else if (neededSSE == 1) { -RegAddr = Address(CGF.Builder.CreateGEP(CGF.Int8Ty, RegSaveArea, fp_offset), - LTy, CharUnits::fromQuantity(16)); } else { assert(neededSSE == 2 && "Invalid number of needed registers!"); // SSE registers are spaced 16 bytes apart in the register save diff --git a/clang/test/CodeGenCXX/x86_64-vaarg.cpp b/clang/test/CodeGenCXX/x86_64-vaarg.cpp index c4616a97e20555..1703b74ad10a2f 100644 --- a/clang/test/CodeGenCXX/x86_64-vaarg.cpp +++ b/clang/test/CodeGenCXX/x86_64-vaarg.cpp @@ -29,6 +29,7 @@ typedef struct { // CHECK-NEXT:[[RETVAL:%.*]] = alloca [[STRUCT_S1:%.*]], align 8 // CHECK-NEXT:[[Z_ADDR:%.*]] = alloca i32, align 4 // CHECK-NEXT:[[LIST:%.*]] = alloca [1 x %struct.__va_list_tag], align 16 +// CHECK-NEXT:[[TMP:%.*]] = alloca [[STRUCT_S1]], align 8 // CHECK-NEXT:store i32 [[Z:%.*]], ptr [[Z_ADDR]], align 4 // CHECK-NEXT:[[ARRAYDECAY:%.*]] = getelementptr inbounds [1 x %struct.__va_list_tag], ptr [[LIST]], i64 0, i64 0 // CHECK-NEXT:call void @llvm.va_start.p0(ptr [[ARRAYDECAY]]) @@ -41,8 +42,11 @@ typedef struct { // CHECK-NEXT:[[TMP0:%.*]] = getelementptr inbounds [[STRUCT___VA_LIST_TAG]], ptr [[ARRAYDECAY1]], i32 0, i32 3 // CHECK-NEXT:[[REG_SAVE_AREA:%.*]] = load ptr, ptr [[TMP0]], align 16 // CHECK-NEXT:[[TMP1:%.*]] = getelementptr i8, ptr [[REG_SAVE_AREA]], i32 [[FP_OFFSET]] -// CHECK-NEXT:[[TMP2:%.*]] = add i32 [[FP_OFFSET]], 16 -// CHECK-NEXT:store i32 [[TMP2]], ptr [[FP_OFFSET_P]], align 4 +// CHECK-NEXT:[[TMP2:%.*]] = load double, ptr [[TMP1]], align 8 +// CHECK-NEXT:[[TMP3:%.*]] = getelementptr i8, ptr [[TMP]], i32 8 +// CHECK-NEXT:store double [[TMP2]], ptr [[TMP3]], align 8 +// CHECK-NEXT:[[TMP4:%.*]] = add i32 [[FP_OFFSET]], 16 +// CHECK-NEXT:store i32 [[TMP4]], ptr [[FP_OFFSET_P]], align 4 // CHECK-NEXT:br label [[VAARG_END:
[clang] [X86_64] Fix empty field error in vaarg of C++. (PR #101639)
@@ -3124,26 +3124,76 @@ RValue X86_64ABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, CGF.Builder.CreateStore(V, CGF.Builder.CreateStructGEP(Tmp, 1)); RegAddr = Tmp.withElementType(LTy); - } else if (neededInt) { -RegAddr = Address(CGF.Builder.CreateGEP(CGF.Int8Ty, RegSaveArea, gp_offset), - LTy, CharUnits::fromQuantity(8)); - + } else if (neededInt || neededSSE == 1) { // Copy to a temporary if necessary to ensure the appropriate alignment. auto TInfo = getContext().getTypeInfoInChars(Ty); uint64_t TySize = TInfo.Width.getQuantity(); CharUnits TyAlign = TInfo.Align; +llvm::Type *CoTy = nullptr; +uint64_t RegSize = TySize; +if (AI.isDirect()) + CoTy = AI.getCoerceToType(); +// Obtain the actual register storage size. +if (CoTy) { + if (CoTy->isStructTy()) { +RegSize = 0; +auto ST = cast(CoTy); +for (unsigned i = 0; i < ST->getNumElements(); ++i) { + auto elementType = ST->getElementType(i); + RegSize += CGF.CGM.getDataLayout().getTypeAllocSize(elementType); +} + } else { +RegSize = CGF.CGM.getDataLayout().getTypeAllocSize(CoTy); + } +} -// Copy into a temporary if the type is more aligned than the -// register save area. -if (TyAlign.getQuantity() > 8) { +llvm::Value *GpOrFpOffset = neededInt ? gp_offset : fp_offset; +uint64_t Alignment = neededInt ? 8 : 16; +// There are two cases require special handling: +// 1) +//``` +//struct { +// struct {} a[8]; +// int b; +//}; +//``` +//The lower 8 bytes of the structure are not stored, +//so an 8-byte offset is needed when accessing the structure. +// 2) +// ``` +// struct { +// long long a; +// int b; CoTinker wrote: Yeah, you're right. https://github.com/llvm/llvm-project/pull/101639 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [X86_64] Fix empty field error in vaarg of C++. (PR #101639)
https://github.com/CoTinker updated https://github.com/llvm/llvm-project/pull/101639 >From a1d5fffca7b8a63efa338f1aeac3a516145ca569 Mon Sep 17 00:00:00 2001 From: Longsheng Mou Date: Fri, 2 Aug 2024 16:36:31 +0800 Subject: [PATCH 1/2] [X86_64] Fix empty field error in vaarg of C++. Such struct types: ``` struct { struct{} a; long long b; }; stuct { struct{} a; double b; }; ``` For such structures, Lo is NoClass and Hi is Integer/SSE. And when this structure argument is passed, the high part is passed at offset 8 in memory. So we should do special handling for these types in EmitVAArg. --- clang/lib/CodeGen/Targets/X86.cpp | 38 +++-- clang/test/CodeGenCXX/x86_64-vaarg.cpp | 211 - 2 files changed, 231 insertions(+), 18 deletions(-) diff --git a/clang/lib/CodeGen/Targets/X86.cpp b/clang/lib/CodeGen/Targets/X86.cpp index 26ff4e4ac0a3b5..0347bd01f82ef3 100644 --- a/clang/lib/CodeGen/Targets/X86.cpp +++ b/clang/lib/CodeGen/Targets/X86.cpp @@ -3124,26 +3124,40 @@ RValue X86_64ABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, CGF.Builder.CreateStore(V, CGF.Builder.CreateStructGEP(Tmp, 1)); RegAddr = Tmp.withElementType(LTy); - } else if (neededInt) { -RegAddr = Address(CGF.Builder.CreateGEP(CGF.Int8Ty, RegSaveArea, gp_offset), - LTy, CharUnits::fromQuantity(8)); - + } else if (neededInt || neededSSE == 1) { // Copy to a temporary if necessary to ensure the appropriate alignment. auto TInfo = getContext().getTypeInfoInChars(Ty); uint64_t TySize = TInfo.Width.getQuantity(); CharUnits TyAlign = TInfo.Align; -// Copy into a temporary if the type is more aligned than the -// register save area. -if (TyAlign.getQuantity() > 8) { +llvm::Value *GpOrFpOffset = neededInt ? gp_offset : fp_offset; +uint64_t Alignment = neededInt ? 8 : 16; +if (auto Offset = AI.getDirectOffset()) { Address Tmp = CGF.CreateMemTemp(Ty); - CGF.Builder.CreateMemCpy(Tmp, RegAddr, TySize, false); - RegAddr = Tmp; + llvm::Type *TyHi = AI.getCoerceToType(); + llvm::Value *Addr = + CGF.Builder.CreateGEP(CGF.Int8Ty, RegSaveArea, GpOrFpOffset); + llvm::Value *Src = CGF.Builder.CreateAlignedLoad(TyHi, Addr, TyAlign); + llvm::Value *PtrOffset = llvm::ConstantInt::get(CGF.Int32Ty, Offset); + Address Dst = Address( + CGF.Builder.CreateGEP(CGF.Int8Ty, Tmp.getBasePointer(), PtrOffset), + LTy, TyAlign); + CGF.Builder.CreateStore(Src, Dst); + RegAddr = Tmp.withElementType(LTy); +} else { + RegAddr = + Address(CGF.Builder.CreateGEP(CGF.Int8Ty, RegSaveArea, GpOrFpOffset), + LTy, CharUnits::fromQuantity(Alignment)); + + // Copy into a temporary if the type is more aligned than the + // register save area. + if (neededInt && TyAlign.getQuantity() > 8) { +Address Tmp = CGF.CreateMemTemp(Ty); +CGF.Builder.CreateMemCpy(Tmp, RegAddr, TySize, false); +RegAddr = Tmp; + } } - } else if (neededSSE == 1) { -RegAddr = Address(CGF.Builder.CreateGEP(CGF.Int8Ty, RegSaveArea, fp_offset), - LTy, CharUnits::fromQuantity(16)); } else { assert(neededSSE == 2 && "Invalid number of needed registers!"); // SSE registers are spaced 16 bytes apart in the register save diff --git a/clang/test/CodeGenCXX/x86_64-vaarg.cpp b/clang/test/CodeGenCXX/x86_64-vaarg.cpp index 439a66deb4fde7..0925d3fe81e139 100644 --- a/clang/test/CodeGenCXX/x86_64-vaarg.cpp +++ b/clang/test/CodeGenCXX/x86_64-vaarg.cpp @@ -29,6 +29,7 @@ typedef struct { // CHECK-NEXT:[[RETVAL:%.*]] = alloca [[STRUCT_S1:%.*]], align 8 // CHECK-NEXT:[[Z_ADDR:%.*]] = alloca i32, align 4 // CHECK-NEXT:[[LIST:%.*]] = alloca [1 x %struct.__va_list_tag], align 16 +// CHECK-NEXT:[[TMP:%.*]] = alloca [[STRUCT_S1]], align 8 // CHECK-NEXT:store i32 [[Z:%.*]], ptr [[Z_ADDR]], align 4 // CHECK-NEXT:[[ARRAYDECAY:%.*]] = getelementptr inbounds [1 x %struct.__va_list_tag], ptr [[LIST]], i64 0, i64 0 // CHECK-NEXT:call void @llvm.va_start.p0(ptr [[ARRAYDECAY]]) @@ -41,8 +42,11 @@ typedef struct { // CHECK-NEXT:[[TMP0:%.*]] = getelementptr inbounds nuw [[STRUCT___VA_LIST_TAG]], ptr [[ARRAYDECAY1]], i32 0, i32 3 // CHECK-NEXT:[[REG_SAVE_AREA:%.*]] = load ptr, ptr [[TMP0]], align 16 // CHECK-NEXT:[[TMP1:%.*]] = getelementptr i8, ptr [[REG_SAVE_AREA]], i32 [[FP_OFFSET]] -// CHECK-NEXT:[[TMP2:%.*]] = add i32 [[FP_OFFSET]], 16 -// CHECK-NEXT:store i32 [[TMP2]], ptr [[FP_OFFSET_P]], align 4 +// CHECK-NEXT:[[TMP2:%.*]] = load double, ptr [[TMP1]], align 8 +// CHECK-NEXT:[[TMP3:%.*]] = getelementptr i8, ptr [[TMP]], i32 8 +// CHECK-NEXT:store double [[TMP2]], ptr [[TMP3]], align 8 +// CHECK-NEXT:[[TMP4:%.*]] = add i32 [[FP_OFFSET]], 16 +// CHECK-NEXT:store i32 [[TMP4]], ptr [[FP_OFFSET_P]], align 4 // CHECK-NEXT:br label [[VAARG_
[clang] [X86_64] Fix empty field error in vaarg of C++. (PR #101639)
@@ -3124,26 +3124,76 @@ RValue X86_64ABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, CGF.Builder.CreateStore(V, CGF.Builder.CreateStructGEP(Tmp, 1)); RegAddr = Tmp.withElementType(LTy); - } else if (neededInt) { -RegAddr = Address(CGF.Builder.CreateGEP(CGF.Int8Ty, RegSaveArea, gp_offset), - LTy, CharUnits::fromQuantity(8)); - + } else if (neededInt || neededSSE == 1) { // Copy to a temporary if necessary to ensure the appropriate alignment. auto TInfo = getContext().getTypeInfoInChars(Ty); uint64_t TySize = TInfo.Width.getQuantity(); CharUnits TyAlign = TInfo.Align; +llvm::Type *CoTy = nullptr; +uint64_t RegSize = TySize; +if (AI.isDirect()) + CoTy = AI.getCoerceToType(); +// Obtain the actual register storage size. +if (CoTy) { + if (CoTy->isStructTy()) { +RegSize = 0; +auto ST = cast(CoTy); +for (unsigned i = 0; i < ST->getNumElements(); ++i) { + auto elementType = ST->getElementType(i); + RegSize += CGF.CGM.getDataLayout().getTypeAllocSize(elementType); +} + } else { +RegSize = CGF.CGM.getDataLayout().getTypeAllocSize(CoTy); + } +} -// Copy into a temporary if the type is more aligned than the -// register save area. -if (TyAlign.getQuantity() > 8) { +llvm::Value *GpOrFpOffset = neededInt ? gp_offset : fp_offset; +uint64_t Alignment = neededInt ? 8 : 16; +// There are two cases require special handling: +// 1) +//``` +//struct { +// struct {} a[8]; +// int b; +//}; +//``` +//The lower 8 bytes of the structure are not stored, +//so an 8-byte offset is needed when accessing the structure. +// 2) +// ``` +// struct { +// long long a; +// int b; CoTinker wrote: SSE size is 16? Consider such structure: ``` struct { double a; struct {} b; } ``` Maybe `RegSize = neededInt ? neededInt * 8 : 8`, I think? https://github.com/llvm/llvm-project/pull/101639 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [X86_64] Fix empty field error in vaarg of C++. (PR #101639)
https://github.com/CoTinker edited https://github.com/llvm/llvm-project/pull/101639 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [X86_64] Fix empty field error in vaarg of C++. (PR #101639)
https://github.com/CoTinker edited https://github.com/llvm/llvm-project/pull/101639 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [X86_64] Fix empty field error in vaarg of C++. (PR #101639)
https://github.com/CoTinker updated https://github.com/llvm/llvm-project/pull/101639 >From a1d5fffca7b8a63efa338f1aeac3a516145ca569 Mon Sep 17 00:00:00 2001 From: Longsheng Mou Date: Fri, 2 Aug 2024 16:36:31 +0800 Subject: [PATCH 1/2] [X86_64] Fix empty field error in vaarg of C++. Such struct types: ``` struct { struct{} a; long long b; }; stuct { struct{} a; double b; }; ``` For such structures, Lo is NoClass and Hi is Integer/SSE. And when this structure argument is passed, the high part is passed at offset 8 in memory. So we should do special handling for these types in EmitVAArg. --- clang/lib/CodeGen/Targets/X86.cpp | 38 +++-- clang/test/CodeGenCXX/x86_64-vaarg.cpp | 211 - 2 files changed, 231 insertions(+), 18 deletions(-) diff --git a/clang/lib/CodeGen/Targets/X86.cpp b/clang/lib/CodeGen/Targets/X86.cpp index 26ff4e4ac0a3b5..0347bd01f82ef3 100644 --- a/clang/lib/CodeGen/Targets/X86.cpp +++ b/clang/lib/CodeGen/Targets/X86.cpp @@ -3124,26 +3124,40 @@ RValue X86_64ABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, CGF.Builder.CreateStore(V, CGF.Builder.CreateStructGEP(Tmp, 1)); RegAddr = Tmp.withElementType(LTy); - } else if (neededInt) { -RegAddr = Address(CGF.Builder.CreateGEP(CGF.Int8Ty, RegSaveArea, gp_offset), - LTy, CharUnits::fromQuantity(8)); - + } else if (neededInt || neededSSE == 1) { // Copy to a temporary if necessary to ensure the appropriate alignment. auto TInfo = getContext().getTypeInfoInChars(Ty); uint64_t TySize = TInfo.Width.getQuantity(); CharUnits TyAlign = TInfo.Align; -// Copy into a temporary if the type is more aligned than the -// register save area. -if (TyAlign.getQuantity() > 8) { +llvm::Value *GpOrFpOffset = neededInt ? gp_offset : fp_offset; +uint64_t Alignment = neededInt ? 8 : 16; +if (auto Offset = AI.getDirectOffset()) { Address Tmp = CGF.CreateMemTemp(Ty); - CGF.Builder.CreateMemCpy(Tmp, RegAddr, TySize, false); - RegAddr = Tmp; + llvm::Type *TyHi = AI.getCoerceToType(); + llvm::Value *Addr = + CGF.Builder.CreateGEP(CGF.Int8Ty, RegSaveArea, GpOrFpOffset); + llvm::Value *Src = CGF.Builder.CreateAlignedLoad(TyHi, Addr, TyAlign); + llvm::Value *PtrOffset = llvm::ConstantInt::get(CGF.Int32Ty, Offset); + Address Dst = Address( + CGF.Builder.CreateGEP(CGF.Int8Ty, Tmp.getBasePointer(), PtrOffset), + LTy, TyAlign); + CGF.Builder.CreateStore(Src, Dst); + RegAddr = Tmp.withElementType(LTy); +} else { + RegAddr = + Address(CGF.Builder.CreateGEP(CGF.Int8Ty, RegSaveArea, GpOrFpOffset), + LTy, CharUnits::fromQuantity(Alignment)); + + // Copy into a temporary if the type is more aligned than the + // register save area. + if (neededInt && TyAlign.getQuantity() > 8) { +Address Tmp = CGF.CreateMemTemp(Ty); +CGF.Builder.CreateMemCpy(Tmp, RegAddr, TySize, false); +RegAddr = Tmp; + } } - } else if (neededSSE == 1) { -RegAddr = Address(CGF.Builder.CreateGEP(CGF.Int8Ty, RegSaveArea, fp_offset), - LTy, CharUnits::fromQuantity(16)); } else { assert(neededSSE == 2 && "Invalid number of needed registers!"); // SSE registers are spaced 16 bytes apart in the register save diff --git a/clang/test/CodeGenCXX/x86_64-vaarg.cpp b/clang/test/CodeGenCXX/x86_64-vaarg.cpp index 439a66deb4fde7..0925d3fe81e139 100644 --- a/clang/test/CodeGenCXX/x86_64-vaarg.cpp +++ b/clang/test/CodeGenCXX/x86_64-vaarg.cpp @@ -29,6 +29,7 @@ typedef struct { // CHECK-NEXT:[[RETVAL:%.*]] = alloca [[STRUCT_S1:%.*]], align 8 // CHECK-NEXT:[[Z_ADDR:%.*]] = alloca i32, align 4 // CHECK-NEXT:[[LIST:%.*]] = alloca [1 x %struct.__va_list_tag], align 16 +// CHECK-NEXT:[[TMP:%.*]] = alloca [[STRUCT_S1]], align 8 // CHECK-NEXT:store i32 [[Z:%.*]], ptr [[Z_ADDR]], align 4 // CHECK-NEXT:[[ARRAYDECAY:%.*]] = getelementptr inbounds [1 x %struct.__va_list_tag], ptr [[LIST]], i64 0, i64 0 // CHECK-NEXT:call void @llvm.va_start.p0(ptr [[ARRAYDECAY]]) @@ -41,8 +42,11 @@ typedef struct { // CHECK-NEXT:[[TMP0:%.*]] = getelementptr inbounds nuw [[STRUCT___VA_LIST_TAG]], ptr [[ARRAYDECAY1]], i32 0, i32 3 // CHECK-NEXT:[[REG_SAVE_AREA:%.*]] = load ptr, ptr [[TMP0]], align 16 // CHECK-NEXT:[[TMP1:%.*]] = getelementptr i8, ptr [[REG_SAVE_AREA]], i32 [[FP_OFFSET]] -// CHECK-NEXT:[[TMP2:%.*]] = add i32 [[FP_OFFSET]], 16 -// CHECK-NEXT:store i32 [[TMP2]], ptr [[FP_OFFSET_P]], align 4 +// CHECK-NEXT:[[TMP2:%.*]] = load double, ptr [[TMP1]], align 8 +// CHECK-NEXT:[[TMP3:%.*]] = getelementptr i8, ptr [[TMP]], i32 8 +// CHECK-NEXT:store double [[TMP2]], ptr [[TMP3]], align 8 +// CHECK-NEXT:[[TMP4:%.*]] = add i32 [[FP_OFFSET]], 16 +// CHECK-NEXT:store i32 [[TMP4]], ptr [[FP_OFFSET_P]], align 4 // CHECK-NEXT:br label [[VAARG_
[clang] [X86_64] Fix empty field error in vaarg of C++. (PR #101639)
https://github.com/CoTinker updated https://github.com/llvm/llvm-project/pull/101639 >From a1d5fffca7b8a63efa338f1aeac3a516145ca569 Mon Sep 17 00:00:00 2001 From: Longsheng Mou Date: Fri, 2 Aug 2024 16:36:31 +0800 Subject: [PATCH 1/2] [X86_64] Fix empty field error in vaarg of C++. Such struct types: ``` struct { struct{} a; long long b; }; stuct { struct{} a; double b; }; ``` For such structures, Lo is NoClass and Hi is Integer/SSE. And when this structure argument is passed, the high part is passed at offset 8 in memory. So we should do special handling for these types in EmitVAArg. --- clang/lib/CodeGen/Targets/X86.cpp | 38 +++-- clang/test/CodeGenCXX/x86_64-vaarg.cpp | 211 - 2 files changed, 231 insertions(+), 18 deletions(-) diff --git a/clang/lib/CodeGen/Targets/X86.cpp b/clang/lib/CodeGen/Targets/X86.cpp index 26ff4e4ac0a3b5..0347bd01f82ef3 100644 --- a/clang/lib/CodeGen/Targets/X86.cpp +++ b/clang/lib/CodeGen/Targets/X86.cpp @@ -3124,26 +3124,40 @@ RValue X86_64ABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, CGF.Builder.CreateStore(V, CGF.Builder.CreateStructGEP(Tmp, 1)); RegAddr = Tmp.withElementType(LTy); - } else if (neededInt) { -RegAddr = Address(CGF.Builder.CreateGEP(CGF.Int8Ty, RegSaveArea, gp_offset), - LTy, CharUnits::fromQuantity(8)); - + } else if (neededInt || neededSSE == 1) { // Copy to a temporary if necessary to ensure the appropriate alignment. auto TInfo = getContext().getTypeInfoInChars(Ty); uint64_t TySize = TInfo.Width.getQuantity(); CharUnits TyAlign = TInfo.Align; -// Copy into a temporary if the type is more aligned than the -// register save area. -if (TyAlign.getQuantity() > 8) { +llvm::Value *GpOrFpOffset = neededInt ? gp_offset : fp_offset; +uint64_t Alignment = neededInt ? 8 : 16; +if (auto Offset = AI.getDirectOffset()) { Address Tmp = CGF.CreateMemTemp(Ty); - CGF.Builder.CreateMemCpy(Tmp, RegAddr, TySize, false); - RegAddr = Tmp; + llvm::Type *TyHi = AI.getCoerceToType(); + llvm::Value *Addr = + CGF.Builder.CreateGEP(CGF.Int8Ty, RegSaveArea, GpOrFpOffset); + llvm::Value *Src = CGF.Builder.CreateAlignedLoad(TyHi, Addr, TyAlign); + llvm::Value *PtrOffset = llvm::ConstantInt::get(CGF.Int32Ty, Offset); + Address Dst = Address( + CGF.Builder.CreateGEP(CGF.Int8Ty, Tmp.getBasePointer(), PtrOffset), + LTy, TyAlign); + CGF.Builder.CreateStore(Src, Dst); + RegAddr = Tmp.withElementType(LTy); +} else { + RegAddr = + Address(CGF.Builder.CreateGEP(CGF.Int8Ty, RegSaveArea, GpOrFpOffset), + LTy, CharUnits::fromQuantity(Alignment)); + + // Copy into a temporary if the type is more aligned than the + // register save area. + if (neededInt && TyAlign.getQuantity() > 8) { +Address Tmp = CGF.CreateMemTemp(Ty); +CGF.Builder.CreateMemCpy(Tmp, RegAddr, TySize, false); +RegAddr = Tmp; + } } - } else if (neededSSE == 1) { -RegAddr = Address(CGF.Builder.CreateGEP(CGF.Int8Ty, RegSaveArea, fp_offset), - LTy, CharUnits::fromQuantity(16)); } else { assert(neededSSE == 2 && "Invalid number of needed registers!"); // SSE registers are spaced 16 bytes apart in the register save diff --git a/clang/test/CodeGenCXX/x86_64-vaarg.cpp b/clang/test/CodeGenCXX/x86_64-vaarg.cpp index 439a66deb4fde7..0925d3fe81e139 100644 --- a/clang/test/CodeGenCXX/x86_64-vaarg.cpp +++ b/clang/test/CodeGenCXX/x86_64-vaarg.cpp @@ -29,6 +29,7 @@ typedef struct { // CHECK-NEXT:[[RETVAL:%.*]] = alloca [[STRUCT_S1:%.*]], align 8 // CHECK-NEXT:[[Z_ADDR:%.*]] = alloca i32, align 4 // CHECK-NEXT:[[LIST:%.*]] = alloca [1 x %struct.__va_list_tag], align 16 +// CHECK-NEXT:[[TMP:%.*]] = alloca [[STRUCT_S1]], align 8 // CHECK-NEXT:store i32 [[Z:%.*]], ptr [[Z_ADDR]], align 4 // CHECK-NEXT:[[ARRAYDECAY:%.*]] = getelementptr inbounds [1 x %struct.__va_list_tag], ptr [[LIST]], i64 0, i64 0 // CHECK-NEXT:call void @llvm.va_start.p0(ptr [[ARRAYDECAY]]) @@ -41,8 +42,11 @@ typedef struct { // CHECK-NEXT:[[TMP0:%.*]] = getelementptr inbounds nuw [[STRUCT___VA_LIST_TAG]], ptr [[ARRAYDECAY1]], i32 0, i32 3 // CHECK-NEXT:[[REG_SAVE_AREA:%.*]] = load ptr, ptr [[TMP0]], align 16 // CHECK-NEXT:[[TMP1:%.*]] = getelementptr i8, ptr [[REG_SAVE_AREA]], i32 [[FP_OFFSET]] -// CHECK-NEXT:[[TMP2:%.*]] = add i32 [[FP_OFFSET]], 16 -// CHECK-NEXT:store i32 [[TMP2]], ptr [[FP_OFFSET_P]], align 4 +// CHECK-NEXT:[[TMP2:%.*]] = load double, ptr [[TMP1]], align 8 +// CHECK-NEXT:[[TMP3:%.*]] = getelementptr i8, ptr [[TMP]], i32 8 +// CHECK-NEXT:store double [[TMP2]], ptr [[TMP3]], align 8 +// CHECK-NEXT:[[TMP4:%.*]] = add i32 [[FP_OFFSET]], 16 +// CHECK-NEXT:store i32 [[TMP4]], ptr [[FP_OFFSET_P]], align 4 // CHECK-NEXT:br label [[VAARG_
[clang] [X86_64] Fix empty field error in vaarg of C++. (PR #101639)
https://github.com/CoTinker updated https://github.com/llvm/llvm-project/pull/101639 >From 3ff5909e6c0cc7acff96ed4e8524a3b5949b209f Mon Sep 17 00:00:00 2001 From: Longsheng Mou Date: Fri, 2 Aug 2024 16:36:31 +0800 Subject: [PATCH 1/2] [X86_64] Fix empty field error in vaarg of C++. Such struct types: ``` struct { struct{} a; long long b; }; stuct { struct{} a; double b; }; ``` For such structures, Lo is NoClass and Hi is Integer/SSE. And when this structure argument is passed, the high part is passed at offset 8 in memory. So we should do special handling for these types in EmitVAArg. --- clang/lib/CodeGen/Targets/X86.cpp | 38 +++-- clang/test/CodeGenCXX/x86_64-vaarg.cpp | 211 - 2 files changed, 231 insertions(+), 18 deletions(-) diff --git a/clang/lib/CodeGen/Targets/X86.cpp b/clang/lib/CodeGen/Targets/X86.cpp index 26ff4e4ac0a3b5..0347bd01f82ef3 100644 --- a/clang/lib/CodeGen/Targets/X86.cpp +++ b/clang/lib/CodeGen/Targets/X86.cpp @@ -3124,26 +3124,40 @@ RValue X86_64ABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, CGF.Builder.CreateStore(V, CGF.Builder.CreateStructGEP(Tmp, 1)); RegAddr = Tmp.withElementType(LTy); - } else if (neededInt) { -RegAddr = Address(CGF.Builder.CreateGEP(CGF.Int8Ty, RegSaveArea, gp_offset), - LTy, CharUnits::fromQuantity(8)); - + } else if (neededInt || neededSSE == 1) { // Copy to a temporary if necessary to ensure the appropriate alignment. auto TInfo = getContext().getTypeInfoInChars(Ty); uint64_t TySize = TInfo.Width.getQuantity(); CharUnits TyAlign = TInfo.Align; -// Copy into a temporary if the type is more aligned than the -// register save area. -if (TyAlign.getQuantity() > 8) { +llvm::Value *GpOrFpOffset = neededInt ? gp_offset : fp_offset; +uint64_t Alignment = neededInt ? 8 : 16; +if (auto Offset = AI.getDirectOffset()) { Address Tmp = CGF.CreateMemTemp(Ty); - CGF.Builder.CreateMemCpy(Tmp, RegAddr, TySize, false); - RegAddr = Tmp; + llvm::Type *TyHi = AI.getCoerceToType(); + llvm::Value *Addr = + CGF.Builder.CreateGEP(CGF.Int8Ty, RegSaveArea, GpOrFpOffset); + llvm::Value *Src = CGF.Builder.CreateAlignedLoad(TyHi, Addr, TyAlign); + llvm::Value *PtrOffset = llvm::ConstantInt::get(CGF.Int32Ty, Offset); + Address Dst = Address( + CGF.Builder.CreateGEP(CGF.Int8Ty, Tmp.getBasePointer(), PtrOffset), + LTy, TyAlign); + CGF.Builder.CreateStore(Src, Dst); + RegAddr = Tmp.withElementType(LTy); +} else { + RegAddr = + Address(CGF.Builder.CreateGEP(CGF.Int8Ty, RegSaveArea, GpOrFpOffset), + LTy, CharUnits::fromQuantity(Alignment)); + + // Copy into a temporary if the type is more aligned than the + // register save area. + if (neededInt && TyAlign.getQuantity() > 8) { +Address Tmp = CGF.CreateMemTemp(Ty); +CGF.Builder.CreateMemCpy(Tmp, RegAddr, TySize, false); +RegAddr = Tmp; + } } - } else if (neededSSE == 1) { -RegAddr = Address(CGF.Builder.CreateGEP(CGF.Int8Ty, RegSaveArea, fp_offset), - LTy, CharUnits::fromQuantity(16)); } else { assert(neededSSE == 2 && "Invalid number of needed registers!"); // SSE registers are spaced 16 bytes apart in the register save diff --git a/clang/test/CodeGenCXX/x86_64-vaarg.cpp b/clang/test/CodeGenCXX/x86_64-vaarg.cpp index 439a66deb4fde7..0925d3fe81e139 100644 --- a/clang/test/CodeGenCXX/x86_64-vaarg.cpp +++ b/clang/test/CodeGenCXX/x86_64-vaarg.cpp @@ -29,6 +29,7 @@ typedef struct { // CHECK-NEXT:[[RETVAL:%.*]] = alloca [[STRUCT_S1:%.*]], align 8 // CHECK-NEXT:[[Z_ADDR:%.*]] = alloca i32, align 4 // CHECK-NEXT:[[LIST:%.*]] = alloca [1 x %struct.__va_list_tag], align 16 +// CHECK-NEXT:[[TMP:%.*]] = alloca [[STRUCT_S1]], align 8 // CHECK-NEXT:store i32 [[Z:%.*]], ptr [[Z_ADDR]], align 4 // CHECK-NEXT:[[ARRAYDECAY:%.*]] = getelementptr inbounds [1 x %struct.__va_list_tag], ptr [[LIST]], i64 0, i64 0 // CHECK-NEXT:call void @llvm.va_start.p0(ptr [[ARRAYDECAY]]) @@ -41,8 +42,11 @@ typedef struct { // CHECK-NEXT:[[TMP0:%.*]] = getelementptr inbounds nuw [[STRUCT___VA_LIST_TAG]], ptr [[ARRAYDECAY1]], i32 0, i32 3 // CHECK-NEXT:[[REG_SAVE_AREA:%.*]] = load ptr, ptr [[TMP0]], align 16 // CHECK-NEXT:[[TMP1:%.*]] = getelementptr i8, ptr [[REG_SAVE_AREA]], i32 [[FP_OFFSET]] -// CHECK-NEXT:[[TMP2:%.*]] = add i32 [[FP_OFFSET]], 16 -// CHECK-NEXT:store i32 [[TMP2]], ptr [[FP_OFFSET_P]], align 4 +// CHECK-NEXT:[[TMP2:%.*]] = load double, ptr [[TMP1]], align 8 +// CHECK-NEXT:[[TMP3:%.*]] = getelementptr i8, ptr [[TMP]], i32 8 +// CHECK-NEXT:store double [[TMP2]], ptr [[TMP3]], align 8 +// CHECK-NEXT:[[TMP4:%.*]] = add i32 [[FP_OFFSET]], 16 +// CHECK-NEXT:store i32 [[TMP4]], ptr [[FP_OFFSET_P]], align 4 // CHECK-NEXT:br label [[VAARG_
[clang] [X86_64] Fix empty field error in vaarg of C++. (PR #101639)
https://github.com/CoTinker updated https://github.com/llvm/llvm-project/pull/101639 >From 3ff5909e6c0cc7acff96ed4e8524a3b5949b209f Mon Sep 17 00:00:00 2001 From: Longsheng Mou Date: Fri, 2 Aug 2024 16:36:31 +0800 Subject: [PATCH 1/3] [X86_64] Fix empty field error in vaarg of C++. Such struct types: ``` struct { struct{} a; long long b; }; stuct { struct{} a; double b; }; ``` For such structures, Lo is NoClass and Hi is Integer/SSE. And when this structure argument is passed, the high part is passed at offset 8 in memory. So we should do special handling for these types in EmitVAArg. --- clang/lib/CodeGen/Targets/X86.cpp | 38 +++-- clang/test/CodeGenCXX/x86_64-vaarg.cpp | 211 - 2 files changed, 231 insertions(+), 18 deletions(-) diff --git a/clang/lib/CodeGen/Targets/X86.cpp b/clang/lib/CodeGen/Targets/X86.cpp index 26ff4e4ac0a3b5..0347bd01f82ef3 100644 --- a/clang/lib/CodeGen/Targets/X86.cpp +++ b/clang/lib/CodeGen/Targets/X86.cpp @@ -3124,26 +3124,40 @@ RValue X86_64ABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, CGF.Builder.CreateStore(V, CGF.Builder.CreateStructGEP(Tmp, 1)); RegAddr = Tmp.withElementType(LTy); - } else if (neededInt) { -RegAddr = Address(CGF.Builder.CreateGEP(CGF.Int8Ty, RegSaveArea, gp_offset), - LTy, CharUnits::fromQuantity(8)); - + } else if (neededInt || neededSSE == 1) { // Copy to a temporary if necessary to ensure the appropriate alignment. auto TInfo = getContext().getTypeInfoInChars(Ty); uint64_t TySize = TInfo.Width.getQuantity(); CharUnits TyAlign = TInfo.Align; -// Copy into a temporary if the type is more aligned than the -// register save area. -if (TyAlign.getQuantity() > 8) { +llvm::Value *GpOrFpOffset = neededInt ? gp_offset : fp_offset; +uint64_t Alignment = neededInt ? 8 : 16; +if (auto Offset = AI.getDirectOffset()) { Address Tmp = CGF.CreateMemTemp(Ty); - CGF.Builder.CreateMemCpy(Tmp, RegAddr, TySize, false); - RegAddr = Tmp; + llvm::Type *TyHi = AI.getCoerceToType(); + llvm::Value *Addr = + CGF.Builder.CreateGEP(CGF.Int8Ty, RegSaveArea, GpOrFpOffset); + llvm::Value *Src = CGF.Builder.CreateAlignedLoad(TyHi, Addr, TyAlign); + llvm::Value *PtrOffset = llvm::ConstantInt::get(CGF.Int32Ty, Offset); + Address Dst = Address( + CGF.Builder.CreateGEP(CGF.Int8Ty, Tmp.getBasePointer(), PtrOffset), + LTy, TyAlign); + CGF.Builder.CreateStore(Src, Dst); + RegAddr = Tmp.withElementType(LTy); +} else { + RegAddr = + Address(CGF.Builder.CreateGEP(CGF.Int8Ty, RegSaveArea, GpOrFpOffset), + LTy, CharUnits::fromQuantity(Alignment)); + + // Copy into a temporary if the type is more aligned than the + // register save area. + if (neededInt && TyAlign.getQuantity() > 8) { +Address Tmp = CGF.CreateMemTemp(Ty); +CGF.Builder.CreateMemCpy(Tmp, RegAddr, TySize, false); +RegAddr = Tmp; + } } - } else if (neededSSE == 1) { -RegAddr = Address(CGF.Builder.CreateGEP(CGF.Int8Ty, RegSaveArea, fp_offset), - LTy, CharUnits::fromQuantity(16)); } else { assert(neededSSE == 2 && "Invalid number of needed registers!"); // SSE registers are spaced 16 bytes apart in the register save diff --git a/clang/test/CodeGenCXX/x86_64-vaarg.cpp b/clang/test/CodeGenCXX/x86_64-vaarg.cpp index 439a66deb4fde7..0925d3fe81e139 100644 --- a/clang/test/CodeGenCXX/x86_64-vaarg.cpp +++ b/clang/test/CodeGenCXX/x86_64-vaarg.cpp @@ -29,6 +29,7 @@ typedef struct { // CHECK-NEXT:[[RETVAL:%.*]] = alloca [[STRUCT_S1:%.*]], align 8 // CHECK-NEXT:[[Z_ADDR:%.*]] = alloca i32, align 4 // CHECK-NEXT:[[LIST:%.*]] = alloca [1 x %struct.__va_list_tag], align 16 +// CHECK-NEXT:[[TMP:%.*]] = alloca [[STRUCT_S1]], align 8 // CHECK-NEXT:store i32 [[Z:%.*]], ptr [[Z_ADDR]], align 4 // CHECK-NEXT:[[ARRAYDECAY:%.*]] = getelementptr inbounds [1 x %struct.__va_list_tag], ptr [[LIST]], i64 0, i64 0 // CHECK-NEXT:call void @llvm.va_start.p0(ptr [[ARRAYDECAY]]) @@ -41,8 +42,11 @@ typedef struct { // CHECK-NEXT:[[TMP0:%.*]] = getelementptr inbounds nuw [[STRUCT___VA_LIST_TAG]], ptr [[ARRAYDECAY1]], i32 0, i32 3 // CHECK-NEXT:[[REG_SAVE_AREA:%.*]] = load ptr, ptr [[TMP0]], align 16 // CHECK-NEXT:[[TMP1:%.*]] = getelementptr i8, ptr [[REG_SAVE_AREA]], i32 [[FP_OFFSET]] -// CHECK-NEXT:[[TMP2:%.*]] = add i32 [[FP_OFFSET]], 16 -// CHECK-NEXT:store i32 [[TMP2]], ptr [[FP_OFFSET_P]], align 4 +// CHECK-NEXT:[[TMP2:%.*]] = load double, ptr [[TMP1]], align 8 +// CHECK-NEXT:[[TMP3:%.*]] = getelementptr i8, ptr [[TMP]], i32 8 +// CHECK-NEXT:store double [[TMP2]], ptr [[TMP3]], align 8 +// CHECK-NEXT:[[TMP4:%.*]] = add i32 [[FP_OFFSET]], 16 +// CHECK-NEXT:store i32 [[TMP4]], ptr [[FP_OFFSET_P]], align 4 // CHECK-NEXT:br label [[VAARG_
[clang] [X86_64] Fix empty field error in vaarg of C++. (PR #101639)
https://github.com/CoTinker updated https://github.com/llvm/llvm-project/pull/101639 >From 3ff5909e6c0cc7acff96ed4e8524a3b5949b209f Mon Sep 17 00:00:00 2001 From: Longsheng Mou Date: Fri, 2 Aug 2024 16:36:31 +0800 Subject: [PATCH 1/3] [X86_64] Fix empty field error in vaarg of C++. Such struct types: ``` struct { struct{} a; long long b; }; stuct { struct{} a; double b; }; ``` For such structures, Lo is NoClass and Hi is Integer/SSE. And when this structure argument is passed, the high part is passed at offset 8 in memory. So we should do special handling for these types in EmitVAArg. --- clang/lib/CodeGen/Targets/X86.cpp | 38 +++-- clang/test/CodeGenCXX/x86_64-vaarg.cpp | 211 - 2 files changed, 231 insertions(+), 18 deletions(-) diff --git a/clang/lib/CodeGen/Targets/X86.cpp b/clang/lib/CodeGen/Targets/X86.cpp index 26ff4e4ac0a3b5..0347bd01f82ef3 100644 --- a/clang/lib/CodeGen/Targets/X86.cpp +++ b/clang/lib/CodeGen/Targets/X86.cpp @@ -3124,26 +3124,40 @@ RValue X86_64ABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, CGF.Builder.CreateStore(V, CGF.Builder.CreateStructGEP(Tmp, 1)); RegAddr = Tmp.withElementType(LTy); - } else if (neededInt) { -RegAddr = Address(CGF.Builder.CreateGEP(CGF.Int8Ty, RegSaveArea, gp_offset), - LTy, CharUnits::fromQuantity(8)); - + } else if (neededInt || neededSSE == 1) { // Copy to a temporary if necessary to ensure the appropriate alignment. auto TInfo = getContext().getTypeInfoInChars(Ty); uint64_t TySize = TInfo.Width.getQuantity(); CharUnits TyAlign = TInfo.Align; -// Copy into a temporary if the type is more aligned than the -// register save area. -if (TyAlign.getQuantity() > 8) { +llvm::Value *GpOrFpOffset = neededInt ? gp_offset : fp_offset; +uint64_t Alignment = neededInt ? 8 : 16; +if (auto Offset = AI.getDirectOffset()) { Address Tmp = CGF.CreateMemTemp(Ty); - CGF.Builder.CreateMemCpy(Tmp, RegAddr, TySize, false); - RegAddr = Tmp; + llvm::Type *TyHi = AI.getCoerceToType(); + llvm::Value *Addr = + CGF.Builder.CreateGEP(CGF.Int8Ty, RegSaveArea, GpOrFpOffset); + llvm::Value *Src = CGF.Builder.CreateAlignedLoad(TyHi, Addr, TyAlign); + llvm::Value *PtrOffset = llvm::ConstantInt::get(CGF.Int32Ty, Offset); + Address Dst = Address( + CGF.Builder.CreateGEP(CGF.Int8Ty, Tmp.getBasePointer(), PtrOffset), + LTy, TyAlign); + CGF.Builder.CreateStore(Src, Dst); + RegAddr = Tmp.withElementType(LTy); +} else { + RegAddr = + Address(CGF.Builder.CreateGEP(CGF.Int8Ty, RegSaveArea, GpOrFpOffset), + LTy, CharUnits::fromQuantity(Alignment)); + + // Copy into a temporary if the type is more aligned than the + // register save area. + if (neededInt && TyAlign.getQuantity() > 8) { +Address Tmp = CGF.CreateMemTemp(Ty); +CGF.Builder.CreateMemCpy(Tmp, RegAddr, TySize, false); +RegAddr = Tmp; + } } - } else if (neededSSE == 1) { -RegAddr = Address(CGF.Builder.CreateGEP(CGF.Int8Ty, RegSaveArea, fp_offset), - LTy, CharUnits::fromQuantity(16)); } else { assert(neededSSE == 2 && "Invalid number of needed registers!"); // SSE registers are spaced 16 bytes apart in the register save diff --git a/clang/test/CodeGenCXX/x86_64-vaarg.cpp b/clang/test/CodeGenCXX/x86_64-vaarg.cpp index 439a66deb4fde7..0925d3fe81e139 100644 --- a/clang/test/CodeGenCXX/x86_64-vaarg.cpp +++ b/clang/test/CodeGenCXX/x86_64-vaarg.cpp @@ -29,6 +29,7 @@ typedef struct { // CHECK-NEXT:[[RETVAL:%.*]] = alloca [[STRUCT_S1:%.*]], align 8 // CHECK-NEXT:[[Z_ADDR:%.*]] = alloca i32, align 4 // CHECK-NEXT:[[LIST:%.*]] = alloca [1 x %struct.__va_list_tag], align 16 +// CHECK-NEXT:[[TMP:%.*]] = alloca [[STRUCT_S1]], align 8 // CHECK-NEXT:store i32 [[Z:%.*]], ptr [[Z_ADDR]], align 4 // CHECK-NEXT:[[ARRAYDECAY:%.*]] = getelementptr inbounds [1 x %struct.__va_list_tag], ptr [[LIST]], i64 0, i64 0 // CHECK-NEXT:call void @llvm.va_start.p0(ptr [[ARRAYDECAY]]) @@ -41,8 +42,11 @@ typedef struct { // CHECK-NEXT:[[TMP0:%.*]] = getelementptr inbounds nuw [[STRUCT___VA_LIST_TAG]], ptr [[ARRAYDECAY1]], i32 0, i32 3 // CHECK-NEXT:[[REG_SAVE_AREA:%.*]] = load ptr, ptr [[TMP0]], align 16 // CHECK-NEXT:[[TMP1:%.*]] = getelementptr i8, ptr [[REG_SAVE_AREA]], i32 [[FP_OFFSET]] -// CHECK-NEXT:[[TMP2:%.*]] = add i32 [[FP_OFFSET]], 16 -// CHECK-NEXT:store i32 [[TMP2]], ptr [[FP_OFFSET_P]], align 4 +// CHECK-NEXT:[[TMP2:%.*]] = load double, ptr [[TMP1]], align 8 +// CHECK-NEXT:[[TMP3:%.*]] = getelementptr i8, ptr [[TMP]], i32 8 +// CHECK-NEXT:store double [[TMP2]], ptr [[TMP3]], align 8 +// CHECK-NEXT:[[TMP4:%.*]] = add i32 [[FP_OFFSET]], 16 +// CHECK-NEXT:store i32 [[TMP4]], ptr [[FP_OFFSET_P]], align 4 // CHECK-NEXT:br label [[VAARG_
[clang] [X86_64] Fix empty field error in vaarg of C++. (PR #101639)
CoTinker wrote: Thanks. https://github.com/llvm/llvm-project/pull/101639 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [X86_64] fix arg pass error in struct. (PR #86902)
@@ -2100,8 +2100,12 @@ void X86_64ABIInfo::classify(QualType Ty, uint64_t OffsetBase, Class &Lo, postMerge(Size, Lo, Hi); return; } + + bool InMemory = Offset % getContext().getTypeAlign(i->getType()) || + (i->getType()->getAs() && CoTinker wrote: I think it's a really good idea. https://github.com/llvm/llvm-project/pull/86902 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [X86_64] fix arg pass error in struct. (PR #86902)
https://github.com/CoTinker updated https://github.com/llvm/llvm-project/pull/86902 >From eb425dbaed73a58b5f8e05e425a1972aa1288fa9 Mon Sep 17 00:00:00 2001 From: Longsheng Mou Date: Fri, 15 Mar 2024 20:50:54 +0800 Subject: [PATCH] [X86_64] fix arg pass error in struct. 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. --- clang/lib/CodeGen/Targets/X86.cpp | 5 - clang/test/CodeGen/X86/x86_64-arguments.c | 18 ++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/clang/lib/CodeGen/Targets/X86.cpp b/clang/lib/CodeGen/Targets/X86.cpp index 1146a851a7715d..535ee2464595d1 100644 --- a/clang/lib/CodeGen/Targets/X86.cpp +++ b/clang/lib/CodeGen/Targets/X86.cpp @@ -2100,8 +2100,11 @@ void X86_64ABIInfo::classify(QualType Ty, uint64_t OffsetBase, Class &Lo, postMerge(Size, Lo, Hi); return; } + + bool IsInMemory = + Offset % getContext().getTypeAlign(i->getType().getCanonicalType()); // Note, skip this test for bit-fields, see below. - if (!BitField && Offset % getContext().getTypeAlign(i->getType())) { + if (!BitField && IsInMemory) { Lo = Memory; postMerge(Size, Lo, Hi); return; diff --git a/clang/test/CodeGen/X86/x86_64-arguments.c b/clang/test/CodeGen/X86/x86_64-arguments.c index cf5636cfd518b6..82845f0a2b31fd 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(ptr noundef byval(%struct.s67) align 8 %x) +void f67(struct s67 x) { +} + +typedef double t68 __attribute__((aligned (4))); +struct s68 { + int a; + t68 b; +}; +// CHECK-LABEL: define{{.*}} void @f68(ptr noundef byval(%struct.s68) align 8 %x) +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: ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [X86_32][C++] fix 0 sized struct case in vaarg. (PR #86388)
https://github.com/CoTinker updated https://github.com/llvm/llvm-project/pull/86388 >From 54f75d7068d0acf336d6d1e61bcf800ff52cc310 Mon Sep 17 00:00:00 2001 From: Longsheng Mou Date: Sat, 23 Mar 2024 17:53:58 +0800 Subject: [PATCH] [X86_32] fix 0 sized struct case in vaarg. struct SuperEmpty { struct{ int a[0];} b;}; Such 0 sized structs in c++ mode can not be ignored in i386 for that c++ fields are never empty.But when EmitVAArg, its size is 0, so that va_list not increase.Maybe we can ignore this kind of arguments. --- clang/lib/CodeGen/Targets/X86.cpp | 4 clang/test/CodeGenCXX/regparm.cpp | 2 +- clang/test/CodeGenCXX/x86_32-vaarg.cpp | 22 ++ 3 files changed, 27 insertions(+), 1 deletion(-) diff --git a/clang/lib/CodeGen/Targets/X86.cpp b/clang/lib/CodeGen/Targets/X86.cpp index 16d52bee3490b..26ff4e4ac0a3b 100644 --- a/clang/lib/CodeGen/Targets/X86.cpp +++ b/clang/lib/CodeGen/Targets/X86.cpp @@ -795,6 +795,10 @@ ABIArgInfo X86_32ABIInfo::classifyArgumentType(QualType Ty, CCState &State, if (!IsWin32StructABI && isEmptyRecord(getContext(), Ty, true)) return ABIArgInfo::getIgnore(); +// Ignore 0 sized structs. +if (TI.Width == 0) + return ABIArgInfo::getIgnore(); + llvm::LLVMContext &LLVMContext = getVMContext(); llvm::IntegerType *Int32 = llvm::Type::getInt32Ty(LLVMContext); bool NeedsPadding = false; diff --git a/clang/test/CodeGenCXX/regparm.cpp b/clang/test/CodeGenCXX/regparm.cpp index 1fd471c2d0727..b9735485db8de 100644 --- a/clang/test/CodeGenCXX/regparm.cpp +++ b/clang/test/CodeGenCXX/regparm.cpp @@ -32,7 +32,7 @@ struct S3 { } a; }; __attribute((regparm(2))) void foo4(S3 a, int b); -// CHECK: declare void @_Z4foo42S3i(ptr noundef byval(%struct.S3) align 4, i32 inreg noundef) +// CHECK: declare void @_Z4foo42S3i(i32 inreg noundef) void bar3(S3 a, int b) { foo4(a, b); } diff --git a/clang/test/CodeGenCXX/x86_32-vaarg.cpp b/clang/test/CodeGenCXX/x86_32-vaarg.cpp index a3f2791484362..90665652a0286 100644 --- a/clang/test/CodeGenCXX/x86_32-vaarg.cpp +++ b/clang/test/CodeGenCXX/x86_32-vaarg.cpp @@ -18,3 +18,25 @@ empty empty_record_test(int z, ...) { __builtin_va_start(list, z); return __builtin_va_arg(list, empty); } + +typedef struct { + struct { +int a[0]; + } b; +} SortOfEmpty; + +// CHECK-LABEL: @_Z18test_sort_of_emptyiz( +// CHECK-NEXT: entry: +// CHECK-NEXT:[[RESULT_PTR:%.*]] = alloca ptr, align 4 +// CHECK-NEXT:[[Z_ADDR:%.*]] = alloca i32, align 4 +// CHECK-NEXT:[[LIST:%.*]] = alloca ptr, align 4 +// CHECK-NEXT:store ptr [[AGG_RESULT:%.*]], ptr [[RESULT_PTR]], align 4 +// CHECK-NEXT:store i32 [[Z:%.*]], ptr [[Z_ADDR]], align 4 +// CHECK-NEXT:call void @llvm.va_start.p0(ptr [[LIST]]) +// CHECK-NEXT:ret void +// +SortOfEmpty test_sort_of_empty(int z, ...) { + __builtin_va_list list; + __builtin_va_start(list, z); + return __builtin_va_arg(list, SortOfEmpty); +} ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [X86_32][C++] fix 0 sized struct case in vaarg. (PR #86388)
https://github.com/CoTinker edited https://github.com/llvm/llvm-project/pull/86388 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [X86_32][C++] fix 0 sized struct case in vaarg. (PR #86388)
CoTinker wrote: Could you please take time to review it, thank you. @efriedma-quic https://github.com/llvm/llvm-project/pull/86388 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [X86_64] Fix empty field error in vaarg of C++. (PR #90389)
https://github.com/CoTinker created https://github.com/llvm/llvm-project/pull/90389 Such struct types: ``` struct { struct{} a; long long b; }; stuct { struct{} a; double b; }; ``` For such structures, Lo is NoClass and Hi is Integer/SSE. And when this structure argument is passed, the high part is passed at offset 8 in memory. So we should do special handling for these types in EmitVAArg. Fix #79790 and #86371. >From 59439be8b4111a0295d42305475a0ac7980b44e7 Mon Sep 17 00:00:00 2001 From: Longsheng Mou Date: Sun, 28 Apr 2024 17:14:29 +0800 Subject: [PATCH] [X86_64] Fix empty field error in vaarg of C++. Such struct types: ``` struct { struct{} a; long long b; }; stuct { struct{} a; double b; }; ``` For such structures, Lo is NoClass and Hi is Integer/SSE. And when this structure argument is passed, the high part is passed at offset 8 in memory. So we should do special handling for these types in EmitVAArg. --- clang/lib/CodeGen/Targets/X86.cpp | 36 +-- clang/test/CodeGenCXX/x86_64-vaarg.cpp | 64 +++--- 2 files changed, 90 insertions(+), 10 deletions(-) diff --git a/clang/lib/CodeGen/Targets/X86.cpp b/clang/lib/CodeGen/Targets/X86.cpp index 94cf0d86f9bed7..525e37d5097f58 100644 --- a/clang/lib/CodeGen/Targets/X86.cpp +++ b/clang/lib/CodeGen/Targets/X86.cpp @@ -3123,8 +3123,22 @@ Address X86_64ABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, RegAddr = Tmp.withElementType(LTy); } else if (neededInt) { -RegAddr = Address(CGF.Builder.CreateGEP(CGF.Int8Ty, RegSaveArea, gp_offset), - LTy, CharUnits::fromQuantity(8)); +if (AI.isDirect() && AI.getDirectOffset() == 8) { + Address Tmp = CGF.CreateMemTemp(Ty); + llvm::StructType *ST = cast(LTy); + Tmp = Tmp.withElementType(ST); + llvm::Type *TyHi = ST->getElementType(1); + llvm::Value *GPAddr = + CGF.Builder.CreateGEP(CGF.Int8Ty, RegSaveArea, gp_offset); + llvm::Value *V = CGF.Builder.CreateAlignedLoad( + TyHi, GPAddr, + CharUnits::fromQuantity(getDataLayout().getABITypeAlign(TyHi))); + CGF.Builder.CreateStore(V, CGF.Builder.CreateStructGEP(Tmp, 1)); + RegAddr = Tmp.withElementType(LTy); +} else + RegAddr = + Address(CGF.Builder.CreateGEP(CGF.Int8Ty, RegSaveArea, gp_offset), + LTy, CharUnits::fromQuantity(8)); // Copy to a temporary if necessary to ensure the appropriate alignment. auto TInfo = getContext().getTypeInfoInChars(Ty); @@ -3140,8 +3154,22 @@ Address X86_64ABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, } } else if (neededSSE == 1) { -RegAddr = Address(CGF.Builder.CreateGEP(CGF.Int8Ty, RegSaveArea, fp_offset), - LTy, CharUnits::fromQuantity(16)); +if (AI.isDirect() && AI.getDirectOffset() == 8) { + Address Tmp = CGF.CreateMemTemp(Ty); + llvm::StructType *ST = cast(LTy); + Tmp = Tmp.withElementType(ST); + llvm::Type *TyHi = ST->getElementType(1); + llvm::Value *FPAddr = + CGF.Builder.CreateGEP(CGF.Int8Ty, RegSaveArea, fp_offset); + llvm::Value *V = CGF.Builder.CreateAlignedLoad( + TyHi, FPAddr, + CharUnits::fromQuantity(getDataLayout().getABITypeAlign(TyHi))); + CGF.Builder.CreateStore(V, CGF.Builder.CreateStructGEP(Tmp, 1)); + RegAddr = Tmp.withElementType(LTy); +} else + RegAddr = + Address(CGF.Builder.CreateGEP(CGF.Int8Ty, RegSaveArea, fp_offset), + LTy, CharUnits::fromQuantity(16)); } else { assert(neededSSE == 2 && "Invalid number of needed registers!"); // SSE registers are spaced 16 bytes apart in the register save diff --git a/clang/test/CodeGenCXX/x86_64-vaarg.cpp b/clang/test/CodeGenCXX/x86_64-vaarg.cpp index 985a0cc41a1410..dc6d9f070cf51f 100644 --- a/clang/test/CodeGenCXX/x86_64-vaarg.cpp +++ b/clang/test/CodeGenCXX/x86_64-vaarg.cpp @@ -32,6 +32,7 @@ typedef struct { // CHECK-NEXT:[[RETVAL:%.*]] = alloca [[STRUCT_S1:%.*]], align 8 // CHECK-NEXT:[[Z_ADDR:%.*]] = alloca i32, align 4 // CHECK-NEXT:[[LIST:%.*]] = alloca [1 x %struct.__va_list_tag], align 16 +// CHECK-NEXT:[[TMP:%.*]] = alloca [[STRUCT_S1]], align 8 // CHECK-NEXT:store i32 [[Z:%.*]], ptr [[Z_ADDR]], align 4 // CHECK-NEXT:[[ARRAYDECAY:%.*]] = getelementptr inbounds [1 x %struct.__va_list_tag], ptr [[LIST]], i64 0, i64 0 // CHECK-NEXT:call void @llvm.va_start.p0(ptr [[ARRAYDECAY]]) @@ -44,8 +45,11 @@ typedef struct { // CHECK-NEXT:[[TMP0:%.*]] = getelementptr inbounds [[STRUCT___VA_LIST_TAG]], ptr [[ARRAYDECAY1]], i32 0, i32 3 // CHECK-NEXT:[[REG_SAVE_AREA:%.*]] = load ptr, ptr [[TMP0]], align 16 // CHECK-NEXT:[[TMP1:%.*]] = getelementptr i8, ptr [[REG_SAVE_AREA]], i32 [[FP_OFFSET]] -// CHECK-NEXT:[[TMP2:%.*]] = add i32 [[FP_OFFSET]], 16 -// CHECK-NEXT:store i32 [[TMP2]], ptr [[FP_OFFSET_P]], align 4 +// CHECK-NEXT:[[TMP2:%.*
[clang] [X86_64] Fix empty field error in vaarg of C++. (PR #90389)
https://github.com/CoTinker updated https://github.com/llvm/llvm-project/pull/90389 >From 3c1aac31d879ebf172d2b9b6c9a351d967f72606 Mon Sep 17 00:00:00 2001 From: Longsheng Mou Date: Sun, 28 Apr 2024 17:14:29 +0800 Subject: [PATCH] [X86_64] Fix empty field error in vaarg of C++. Such struct types: ``` struct { struct{} a; long long b; }; stuct { struct{} a; double b; }; ``` For such structures, Lo is NoClass and Hi is Integer/SSE. And when this structure argument is passed, the high part is passed at offset 8 in memory. So we should do special handling for these types in EmitVAArg. --- clang/lib/CodeGen/Targets/X86.cpp | 36 +-- clang/test/CodeGenCXX/x86_64-vaarg.cpp | 64 +++--- 2 files changed, 90 insertions(+), 10 deletions(-) diff --git a/clang/lib/CodeGen/Targets/X86.cpp b/clang/lib/CodeGen/Targets/X86.cpp index 94cf0d86f9bed7..525e37d5097f58 100644 --- a/clang/lib/CodeGen/Targets/X86.cpp +++ b/clang/lib/CodeGen/Targets/X86.cpp @@ -3123,8 +3123,22 @@ Address X86_64ABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, RegAddr = Tmp.withElementType(LTy); } else if (neededInt) { -RegAddr = Address(CGF.Builder.CreateGEP(CGF.Int8Ty, RegSaveArea, gp_offset), - LTy, CharUnits::fromQuantity(8)); +if (AI.isDirect() && AI.getDirectOffset() == 8) { + Address Tmp = CGF.CreateMemTemp(Ty); + llvm::StructType *ST = cast(LTy); + Tmp = Tmp.withElementType(ST); + llvm::Type *TyHi = ST->getElementType(1); + llvm::Value *GPAddr = + CGF.Builder.CreateGEP(CGF.Int8Ty, RegSaveArea, gp_offset); + llvm::Value *V = CGF.Builder.CreateAlignedLoad( + TyHi, GPAddr, + CharUnits::fromQuantity(getDataLayout().getABITypeAlign(TyHi))); + CGF.Builder.CreateStore(V, CGF.Builder.CreateStructGEP(Tmp, 1)); + RegAddr = Tmp.withElementType(LTy); +} else + RegAddr = + Address(CGF.Builder.CreateGEP(CGF.Int8Ty, RegSaveArea, gp_offset), + LTy, CharUnits::fromQuantity(8)); // Copy to a temporary if necessary to ensure the appropriate alignment. auto TInfo = getContext().getTypeInfoInChars(Ty); @@ -3140,8 +3154,22 @@ Address X86_64ABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, } } else if (neededSSE == 1) { -RegAddr = Address(CGF.Builder.CreateGEP(CGF.Int8Ty, RegSaveArea, fp_offset), - LTy, CharUnits::fromQuantity(16)); +if (AI.isDirect() && AI.getDirectOffset() == 8) { + Address Tmp = CGF.CreateMemTemp(Ty); + llvm::StructType *ST = cast(LTy); + Tmp = Tmp.withElementType(ST); + llvm::Type *TyHi = ST->getElementType(1); + llvm::Value *FPAddr = + CGF.Builder.CreateGEP(CGF.Int8Ty, RegSaveArea, fp_offset); + llvm::Value *V = CGF.Builder.CreateAlignedLoad( + TyHi, FPAddr, + CharUnits::fromQuantity(getDataLayout().getABITypeAlign(TyHi))); + CGF.Builder.CreateStore(V, CGF.Builder.CreateStructGEP(Tmp, 1)); + RegAddr = Tmp.withElementType(LTy); +} else + RegAddr = + Address(CGF.Builder.CreateGEP(CGF.Int8Ty, RegSaveArea, fp_offset), + LTy, CharUnits::fromQuantity(16)); } else { assert(neededSSE == 2 && "Invalid number of needed registers!"); // SSE registers are spaced 16 bytes apart in the register save diff --git a/clang/test/CodeGenCXX/x86_64-vaarg.cpp b/clang/test/CodeGenCXX/x86_64-vaarg.cpp index 985a0cc41a1410..dc6d9f070cf51f 100644 --- a/clang/test/CodeGenCXX/x86_64-vaarg.cpp +++ b/clang/test/CodeGenCXX/x86_64-vaarg.cpp @@ -32,6 +32,7 @@ typedef struct { // CHECK-NEXT:[[RETVAL:%.*]] = alloca [[STRUCT_S1:%.*]], align 8 // CHECK-NEXT:[[Z_ADDR:%.*]] = alloca i32, align 4 // CHECK-NEXT:[[LIST:%.*]] = alloca [1 x %struct.__va_list_tag], align 16 +// CHECK-NEXT:[[TMP:%.*]] = alloca [[STRUCT_S1]], align 8 // CHECK-NEXT:store i32 [[Z:%.*]], ptr [[Z_ADDR]], align 4 // CHECK-NEXT:[[ARRAYDECAY:%.*]] = getelementptr inbounds [1 x %struct.__va_list_tag], ptr [[LIST]], i64 0, i64 0 // CHECK-NEXT:call void @llvm.va_start.p0(ptr [[ARRAYDECAY]]) @@ -44,8 +45,11 @@ typedef struct { // CHECK-NEXT:[[TMP0:%.*]] = getelementptr inbounds [[STRUCT___VA_LIST_TAG]], ptr [[ARRAYDECAY1]], i32 0, i32 3 // CHECK-NEXT:[[REG_SAVE_AREA:%.*]] = load ptr, ptr [[TMP0]], align 16 // CHECK-NEXT:[[TMP1:%.*]] = getelementptr i8, ptr [[REG_SAVE_AREA]], i32 [[FP_OFFSET]] -// CHECK-NEXT:[[TMP2:%.*]] = add i32 [[FP_OFFSET]], 16 -// CHECK-NEXT:store i32 [[TMP2]], ptr [[FP_OFFSET_P]], align 4 +// CHECK-NEXT:[[TMP2:%.*]] = load double, ptr [[TMP1]], align 8 +// CHECK-NEXT:[[TMP3:%.*]] = getelementptr inbounds [[STRUCT_S1]], ptr [[TMP]], i32 0, i32 1 +// CHECK-NEXT:store double [[TMP2]], ptr [[TMP3]], align 8 +// CHECK-NEXT:[[TMP4:%.*]] = add i32 [[FP_OFFSET]], 16 +// CHECK-NEXT:store i32 [[TMP4]], ptr [[FP_OFFSET_P]], align 4 // CHECK-NEXT
[clang] [X86_64] Fix empty field error in vaarg of C++. (PR #90389)
https://github.com/CoTinker updated https://github.com/llvm/llvm-project/pull/90389 >From db18c52f8fd5f397324505bcb2e07343794e5dce Mon Sep 17 00:00:00 2001 From: Longsheng Mou Date: Sun, 28 Apr 2024 17:14:29 +0800 Subject: [PATCH] [X86_64] Fix empty field error in vaarg of C++. Such struct types: ``` struct { struct{} a; long long b; }; stuct { struct{} a; double b; }; ``` For such structures, Lo is NoClass and Hi is Integer/SSE. And when this structure argument is passed, the high part is passed at offset 8 in memory. So we should do special handling for these types in EmitVAArg. --- clang/lib/CodeGen/Targets/X86.cpp | 27 +++ clang/test/CodeGenCXX/x86_64-vaarg.cpp | 64 +++--- 2 files changed, 77 insertions(+), 14 deletions(-) diff --git a/clang/lib/CodeGen/Targets/X86.cpp b/clang/lib/CodeGen/Targets/X86.cpp index 94cf0d86f9bed7..eff54d12ce5496 100644 --- a/clang/lib/CodeGen/Targets/X86.cpp +++ b/clang/lib/CodeGen/Targets/X86.cpp @@ -3122,9 +3122,24 @@ Address X86_64ABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, CGF.Builder.CreateStore(V, CGF.Builder.CreateStructGEP(Tmp, 1)); RegAddr = Tmp.withElementType(LTy); - } else if (neededInt) { -RegAddr = Address(CGF.Builder.CreateGEP(CGF.Int8Ty, RegSaveArea, gp_offset), - LTy, CharUnits::fromQuantity(8)); + } else if (neededInt || neededSSE == 1) { +llvm::Value *Offset = neededInt ? gp_offset : fp_offset; +uint64_t Alignment = neededInt ? 8 : 16; +Address Tmp = CGF.CreateMemTemp(Ty); +if (AI.isDirect() && AI.getDirectOffset() == 8) { + llvm::StructType *ST = cast(LTy); + Tmp = Tmp.withElementType(ST); + llvm::Type *TyHi = AI.getCoerceToType(); + llvm::Value *Addr = + CGF.Builder.CreateGEP(CGF.Int8Ty, RegSaveArea, Offset); + llvm::Value *V = CGF.Builder.CreateAlignedLoad( + TyHi, Addr, + CharUnits::fromQuantity(getDataLayout().getABITypeAlign(TyHi))); + CGF.Builder.CreateStore(V, CGF.Builder.CreateStructGEP(Tmp, 1)); + RegAddr = Tmp.withElementType(LTy); +} else + RegAddr = Address(CGF.Builder.CreateGEP(CGF.Int8Ty, RegSaveArea, Offset), +LTy, CharUnits::fromQuantity(Alignment)); // Copy to a temporary if necessary to ensure the appropriate alignment. auto TInfo = getContext().getTypeInfoInChars(Ty); @@ -3133,15 +3148,11 @@ Address X86_64ABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, // Copy into a temporary if the type is more aligned than the // register save area. -if (TyAlign.getQuantity() > 8) { - Address Tmp = CGF.CreateMemTemp(Ty); +if (neededInt && TyAlign.getQuantity() > 8) { CGF.Builder.CreateMemCpy(Tmp, RegAddr, TySize, false); RegAddr = Tmp; } - } else if (neededSSE == 1) { -RegAddr = Address(CGF.Builder.CreateGEP(CGF.Int8Ty, RegSaveArea, fp_offset), - LTy, CharUnits::fromQuantity(16)); } else { assert(neededSSE == 2 && "Invalid number of needed registers!"); // SSE registers are spaced 16 bytes apart in the register save diff --git a/clang/test/CodeGenCXX/x86_64-vaarg.cpp b/clang/test/CodeGenCXX/x86_64-vaarg.cpp index 985a0cc41a1410..dc6d9f070cf51f 100644 --- a/clang/test/CodeGenCXX/x86_64-vaarg.cpp +++ b/clang/test/CodeGenCXX/x86_64-vaarg.cpp @@ -32,6 +32,7 @@ typedef struct { // CHECK-NEXT:[[RETVAL:%.*]] = alloca [[STRUCT_S1:%.*]], align 8 // CHECK-NEXT:[[Z_ADDR:%.*]] = alloca i32, align 4 // CHECK-NEXT:[[LIST:%.*]] = alloca [1 x %struct.__va_list_tag], align 16 +// CHECK-NEXT:[[TMP:%.*]] = alloca [[STRUCT_S1]], align 8 // CHECK-NEXT:store i32 [[Z:%.*]], ptr [[Z_ADDR]], align 4 // CHECK-NEXT:[[ARRAYDECAY:%.*]] = getelementptr inbounds [1 x %struct.__va_list_tag], ptr [[LIST]], i64 0, i64 0 // CHECK-NEXT:call void @llvm.va_start.p0(ptr [[ARRAYDECAY]]) @@ -44,8 +45,11 @@ typedef struct { // CHECK-NEXT:[[TMP0:%.*]] = getelementptr inbounds [[STRUCT___VA_LIST_TAG]], ptr [[ARRAYDECAY1]], i32 0, i32 3 // CHECK-NEXT:[[REG_SAVE_AREA:%.*]] = load ptr, ptr [[TMP0]], align 16 // CHECK-NEXT:[[TMP1:%.*]] = getelementptr i8, ptr [[REG_SAVE_AREA]], i32 [[FP_OFFSET]] -// CHECK-NEXT:[[TMP2:%.*]] = add i32 [[FP_OFFSET]], 16 -// CHECK-NEXT:store i32 [[TMP2]], ptr [[FP_OFFSET_P]], align 4 +// CHECK-NEXT:[[TMP2:%.*]] = load double, ptr [[TMP1]], align 8 +// CHECK-NEXT:[[TMP3:%.*]] = getelementptr inbounds [[STRUCT_S1]], ptr [[TMP]], i32 0, i32 1 +// CHECK-NEXT:store double [[TMP2]], ptr [[TMP3]], align 8 +// CHECK-NEXT:[[TMP4:%.*]] = add i32 [[FP_OFFSET]], 16 +// CHECK-NEXT:store i32 [[TMP4]], ptr [[FP_OFFSET_P]], align 4 // CHECK-NEXT:br label [[VAARG_END:%.*]] // CHECK: vaarg.in_mem: // CHECK-NEXT:[[OVERFLOW_ARG_AREA_P:%.*]] = getelementptr inbounds [[STRUCT___VA_LIST_TAG]], ptr [[ARRAYDECAY1]], i32 0, i32 2 @@ -54,14 +58,62 @@ typedef struct {
[clang] [X86_64] Fix empty field error in vaarg of C++. (PR #90389)
https://github.com/CoTinker updated https://github.com/llvm/llvm-project/pull/90389 >From 1ce3de25b4ad1e6254eec5e84bf29816aafca6fb Mon Sep 17 00:00:00 2001 From: Longsheng Mou Date: Sun, 28 Apr 2024 17:14:29 +0800 Subject: [PATCH] [X86_64] Fix empty field error in vaarg of C++. Such struct types: ``` struct { struct{} a; long long b; }; stuct { struct{} a; double b; }; ``` For such structures, Lo is NoClass and Hi is Integer/SSE. And when this structure argument is passed, the high part is passed at offset 8 in memory. So we should do special handling for these types in EmitVAArg. --- clang/lib/CodeGen/Targets/X86.cpp | 30 clang/test/CodeGenCXX/x86_64-vaarg.cpp | 64 +++--- 2 files changed, 80 insertions(+), 14 deletions(-) diff --git a/clang/lib/CodeGen/Targets/X86.cpp b/clang/lib/CodeGen/Targets/X86.cpp index 94cf0d86f9bed7..c6a1f5272458f4 100644 --- a/clang/lib/CodeGen/Targets/X86.cpp +++ b/clang/lib/CodeGen/Targets/X86.cpp @@ -3122,9 +3122,25 @@ Address X86_64ABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, CGF.Builder.CreateStore(V, CGF.Builder.CreateStructGEP(Tmp, 1)); RegAddr = Tmp.withElementType(LTy); - } else if (neededInt) { -RegAddr = Address(CGF.Builder.CreateGEP(CGF.Int8Ty, RegSaveArea, gp_offset), - LTy, CharUnits::fromQuantity(8)); + } else if (neededInt || neededSSE == 1) { +llvm::Value *Offset = neededInt ? gp_offset : fp_offset; +uint64_t Alignment = neededInt ? 8 : 16; +Address Tmp = Address::invalid(); +if (AI.isDirect() && AI.getDirectOffset() == 8) { + Tmp = CGF.CreateMemTemp(Ty); + llvm::StructType *ST = cast(LTy); + Tmp = Tmp.withElementType(ST); + llvm::Type *TyHi = AI.getCoerceToType(); + llvm::Value *Addr = + CGF.Builder.CreateGEP(CGF.Int8Ty, RegSaveArea, Offset); + llvm::Value *V = CGF.Builder.CreateAlignedLoad( + TyHi, Addr, + CharUnits::fromQuantity(getDataLayout().getABITypeAlign(TyHi))); + CGF.Builder.CreateStore(V, CGF.Builder.CreateStructGEP(Tmp, 1)); + RegAddr = Tmp.withElementType(LTy); +} else + RegAddr = Address(CGF.Builder.CreateGEP(CGF.Int8Ty, RegSaveArea, Offset), +LTy, CharUnits::fromQuantity(Alignment)); // Copy to a temporary if necessary to ensure the appropriate alignment. auto TInfo = getContext().getTypeInfoInChars(Ty); @@ -3133,15 +3149,13 @@ Address X86_64ABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, // Copy into a temporary if the type is more aligned than the // register save area. -if (TyAlign.getQuantity() > 8) { - Address Tmp = CGF.CreateMemTemp(Ty); +if (neededInt && TyAlign.getQuantity() > 8) { + if (!Tmp.isValid()) +Tmp = CGF.CreateMemTemp(Ty); CGF.Builder.CreateMemCpy(Tmp, RegAddr, TySize, false); RegAddr = Tmp; } - } else if (neededSSE == 1) { -RegAddr = Address(CGF.Builder.CreateGEP(CGF.Int8Ty, RegSaveArea, fp_offset), - LTy, CharUnits::fromQuantity(16)); } else { assert(neededSSE == 2 && "Invalid number of needed registers!"); // SSE registers are spaced 16 bytes apart in the register save diff --git a/clang/test/CodeGenCXX/x86_64-vaarg.cpp b/clang/test/CodeGenCXX/x86_64-vaarg.cpp index 985a0cc41a1410..dc6d9f070cf51f 100644 --- a/clang/test/CodeGenCXX/x86_64-vaarg.cpp +++ b/clang/test/CodeGenCXX/x86_64-vaarg.cpp @@ -32,6 +32,7 @@ typedef struct { // CHECK-NEXT:[[RETVAL:%.*]] = alloca [[STRUCT_S1:%.*]], align 8 // CHECK-NEXT:[[Z_ADDR:%.*]] = alloca i32, align 4 // CHECK-NEXT:[[LIST:%.*]] = alloca [1 x %struct.__va_list_tag], align 16 +// CHECK-NEXT:[[TMP:%.*]] = alloca [[STRUCT_S1]], align 8 // CHECK-NEXT:store i32 [[Z:%.*]], ptr [[Z_ADDR]], align 4 // CHECK-NEXT:[[ARRAYDECAY:%.*]] = getelementptr inbounds [1 x %struct.__va_list_tag], ptr [[LIST]], i64 0, i64 0 // CHECK-NEXT:call void @llvm.va_start.p0(ptr [[ARRAYDECAY]]) @@ -44,8 +45,11 @@ typedef struct { // CHECK-NEXT:[[TMP0:%.*]] = getelementptr inbounds [[STRUCT___VA_LIST_TAG]], ptr [[ARRAYDECAY1]], i32 0, i32 3 // CHECK-NEXT:[[REG_SAVE_AREA:%.*]] = load ptr, ptr [[TMP0]], align 16 // CHECK-NEXT:[[TMP1:%.*]] = getelementptr i8, ptr [[REG_SAVE_AREA]], i32 [[FP_OFFSET]] -// CHECK-NEXT:[[TMP2:%.*]] = add i32 [[FP_OFFSET]], 16 -// CHECK-NEXT:store i32 [[TMP2]], ptr [[FP_OFFSET_P]], align 4 +// CHECK-NEXT:[[TMP2:%.*]] = load double, ptr [[TMP1]], align 8 +// CHECK-NEXT:[[TMP3:%.*]] = getelementptr inbounds [[STRUCT_S1]], ptr [[TMP]], i32 0, i32 1 +// CHECK-NEXT:store double [[TMP2]], ptr [[TMP3]], align 8 +// CHECK-NEXT:[[TMP4:%.*]] = add i32 [[FP_OFFSET]], 16 +// CHECK-NEXT:store i32 [[TMP4]], ptr [[FP_OFFSET_P]], align 4 // CHECK-NEXT:br label [[VAARG_END:%.*]] // CHECK: vaarg.in_mem: // CHECK-NEXT:[[OVERFLOW_ARG_AREA_P:%.*]] = getelementptr inbounds
[clang] [X86_32][C++] fix 0 sized struct case in vaarg. (PR #86388)
CoTinker wrote: Inconsistency here is inevitable. Such struct `SuperEmpty { struct{ int a[0];} b;}` in c++ mode can not be ignored in i386 for that c++ fields are never empty, and its TypeInfo.Width = TypeInfo.Align = 0. https://github.com/llvm/llvm-project/blob/594989918bf9e178f3b7c5e200d700d0574f15ec/clang/lib/CodeGen/Targets/X86.cpp#L1070-L1091 And Indirect is false, so that DirectSize = DirectAlign = 0, which leads to error. https://github.com/llvm/llvm-project/blob/594989918bf9e178f3b7c5e200d700d0574f15ec/clang/lib/CodeGen/ABIInfoImpl.cpp#L205-L230 How do I fix this? Change the classifyArgumentType or the EmiVAArg? @efriedma-quic https://github.com/llvm/llvm-project/pull/86388 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [X86_32][C++] fix 0 sized struct case in vaarg. (PR #86388)
https://github.com/CoTinker closed https://github.com/llvm/llvm-project/pull/86388 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [X86_64] Fix empty field error in vaarg of C++. (PR #90389)
https://github.com/CoTinker closed https://github.com/llvm/llvm-project/pull/90389 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [X86_64] Fix empty field error in vaarg of C++. (PR #101639)
https://github.com/CoTinker created https://github.com/llvm/llvm-project/pull/101639 Such struct types: ``` struct { struct{} a; long long b; }; stuct { struct{} a; double b; }; ``` For such structures, Lo is NoClass and Hi is Integer/SSE. And when this structure argument is passed, the high part is passed at offset 8 in memory. So we should do special handling for these types in EmitVAArg.Fix https://github.com/llvm/llvm-project/issues/79790 and https://github.com/llvm/llvm-project/issues/86371. >From fa8f47190badba495d4ca9c90f0bbeba6ac545a3 Mon Sep 17 00:00:00 2001 From: Longsheng Mou Date: Fri, 2 Aug 2024 16:36:31 +0800 Subject: [PATCH] [X86_64] Fix empty field error in vaarg of C++. Such struct types: ``` struct { struct{} a; long long b; }; stuct { struct{} a; double b; }; ``` For such structures, Lo is NoClass and Hi is Integer/SSE. And when this structure argument is passed, the high part is passed at offset 8 in memory. So we should do special handling for these types in EmitVAArg. --- clang/lib/CodeGen/Targets/X86.cpp | 30 +++- clang/test/CodeGenCXX/x86_64-vaarg.cpp | 211 - 2 files changed, 227 insertions(+), 14 deletions(-) diff --git a/clang/lib/CodeGen/Targets/X86.cpp b/clang/lib/CodeGen/Targets/X86.cpp index 26ff4e4ac0a3b..c7e84f70ae15f 100644 --- a/clang/lib/CodeGen/Targets/X86.cpp +++ b/clang/lib/CodeGen/Targets/X86.cpp @@ -3124,26 +3124,40 @@ RValue X86_64ABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, CGF.Builder.CreateStore(V, CGF.Builder.CreateStructGEP(Tmp, 1)); RegAddr = Tmp.withElementType(LTy); - } else if (neededInt) { -RegAddr = Address(CGF.Builder.CreateGEP(CGF.Int8Ty, RegSaveArea, gp_offset), - LTy, CharUnits::fromQuantity(8)); - + } else if (neededInt || neededSSE == 1) { // Copy to a temporary if necessary to ensure the appropriate alignment. auto TInfo = getContext().getTypeInfoInChars(Ty); uint64_t TySize = TInfo.Width.getQuantity(); CharUnits TyAlign = TInfo.Align; +llvm::Value *GpOrFpOffset = neededInt ? gp_offset : fp_offset; +uint64_t Alignment = neededInt ? 8 : 16; +if (auto Offset = AI.getDirectOffset()) { + Address Tmp = CGF.CreateMemTemp(Ty); + llvm::Type *TyHi = AI.getCoerceToType(); + llvm::Value *Addr = + CGF.Builder.CreateGEP(CGF.Int8Ty, RegSaveArea, GpOrFpOffset); + llvm::Value *Src = CGF.Builder.CreateAlignedLoad(TyHi, Addr, TyAlign); + llvm::Value *PtrOffset = llvm::ConstantInt::get(CGF.Int32Ty, Offset); + Address Dst = Address( + CGF.Builder.CreateGEP(CGF.Int8Ty, Tmp.getBasePointer(), PtrOffset), + LTy, TyAlign); + CGF.Builder.CreateStore(Src, Dst); + RegAddr = Tmp.withElementType(LTy); +} else { + RegAddr = + Address(CGF.Builder.CreateGEP(CGF.Int8Ty, RegSaveArea, GpOrFpOffset), + LTy, CharUnits::fromQuantity(Alignment)); +} + // Copy into a temporary if the type is more aligned than the // register save area. -if (TyAlign.getQuantity() > 8) { +if (neededInt && TyAlign.getQuantity() > 8) { Address Tmp = CGF.CreateMemTemp(Ty); CGF.Builder.CreateMemCpy(Tmp, RegAddr, TySize, false); RegAddr = Tmp; } - } else if (neededSSE == 1) { -RegAddr = Address(CGF.Builder.CreateGEP(CGF.Int8Ty, RegSaveArea, fp_offset), - LTy, CharUnits::fromQuantity(16)); } else { assert(neededSSE == 2 && "Invalid number of needed registers!"); // SSE registers are spaced 16 bytes apart in the register save diff --git a/clang/test/CodeGenCXX/x86_64-vaarg.cpp b/clang/test/CodeGenCXX/x86_64-vaarg.cpp index c4616a97e2055..1703b74ad10a2 100644 --- a/clang/test/CodeGenCXX/x86_64-vaarg.cpp +++ b/clang/test/CodeGenCXX/x86_64-vaarg.cpp @@ -29,6 +29,7 @@ typedef struct { // CHECK-NEXT:[[RETVAL:%.*]] = alloca [[STRUCT_S1:%.*]], align 8 // CHECK-NEXT:[[Z_ADDR:%.*]] = alloca i32, align 4 // CHECK-NEXT:[[LIST:%.*]] = alloca [1 x %struct.__va_list_tag], align 16 +// CHECK-NEXT:[[TMP:%.*]] = alloca [[STRUCT_S1]], align 8 // CHECK-NEXT:store i32 [[Z:%.*]], ptr [[Z_ADDR]], align 4 // CHECK-NEXT:[[ARRAYDECAY:%.*]] = getelementptr inbounds [1 x %struct.__va_list_tag], ptr [[LIST]], i64 0, i64 0 // CHECK-NEXT:call void @llvm.va_start.p0(ptr [[ARRAYDECAY]]) @@ -41,8 +42,11 @@ typedef struct { // CHECK-NEXT:[[TMP0:%.*]] = getelementptr inbounds [[STRUCT___VA_LIST_TAG]], ptr [[ARRAYDECAY1]], i32 0, i32 3 // CHECK-NEXT:[[REG_SAVE_AREA:%.*]] = load ptr, ptr [[TMP0]], align 16 // CHECK-NEXT:[[TMP1:%.*]] = getelementptr i8, ptr [[REG_SAVE_AREA]], i32 [[FP_OFFSET]] -// CHECK-NEXT:[[TMP2:%.*]] = add i32 [[FP_OFFSET]], 16 -// CHECK-NEXT:store i32 [[TMP2]], ptr [[FP_OFFSET_P]], align 4 +// CHECK-NEXT:[[TMP2:%.*]] = load double, ptr [[TMP1]], align 8 +// CHECK-NEXT:[[TMP3:%.*]] = getelementptr i8, ptr [[TMP]], i32 8 +//
[clang] [X86_32][C++] fix 0 sized struct case in vaarg. (PR #86388)
CoTinker wrote: I don't know, but maybe Eli can give you an answer. https://github.com/llvm/llvm-project/pull/86388 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [X86_64] Fix empty field error in vaarg of C++. (PR #101639)
https://github.com/CoTinker edited https://github.com/llvm/llvm-project/pull/101639 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [X86_64] Fix empty field error in vaarg of C++. (PR #101639)
CoTinker wrote: Ping~ https://github.com/llvm/llvm-project/pull/101639 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [lld] [llvm] [mlir] [llvm-project] Fix typo "propogate" (PR #114795)
https://github.com/CoTinker approved this pull request. https://github.com/llvm/llvm-project/pull/114795 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [lld] [llvm] [mlir] [NFC] Use more isa and isa_and_nonnull instead dyn_cast for predicates (PR #137393)
https://github.com/CoTinker approved this pull request. https://github.com/llvm/llvm-project/pull/137393 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [lld] [llvm] [mlir] [NFC] Use more isa and isa_and_nonnull instead dyn_cast for predicates (PR #137393)
https://github.com/CoTinker closed https://github.com/llvm/llvm-project/pull/137393 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [lld] [llvm] [mlir] [NFC] Use more isa and isa_and_nonnull instead dyn_cast for predicates (PR #137393)
CoTinker wrote: The CI not succeed. https://github.com/llvm/llvm-project/pull/137393 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits