diff --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md index bf295981710ac..04a071b726097 100644 --- a/clang/docs/ReleaseNotes.md +++ b/clang/docs/ReleaseNotes.md @@ -101,13 +101,6 @@ features cannot lower the translation-unit ABI level; - On MIPS N32/N64, an `__int128` now correctly start in an even-numbered register or 16-byte aligned stack slot, matching GCC. -- On x86-64 System V, a non-zero-width unnamed bit-field now classifies the - eightbytes it occupies as INTEGER, like a named bit-field, matching GCC. - Aggregates where this changes the classification may be passed or returned - differently -- a struct holding a run of `__int128` bit-fields, for example, - now travels in the two integer registers the ABI assigns it. This also fixes - a crash when such a struct was passed or returned. (#GH202205) - ### AST Dumping Potentially Breaking Changes ### Clang Frontend Potentially Breaking Changes diff --git a/clang/lib/CodeGen/Targets/X86.cpp b/clang/lib/CodeGen/Targets/X86.cpp index d60d71775a9d1..1dc3bd0740baa 100644 --- a/clang/lib/CodeGen/Targets/X86.cpp +++ b/clang/lib/CodeGen/Targets/X86.cpp @@ -2207,9 +2207,8 @@ void X86_64ABIInfo::classify(QualType Ty, uint64_t OffsetBase, Class &Lo, uint64_t Offset = OffsetBase + Layout.getFieldOffset(idx); bool BitField = i->isBitField(); - // Ignore zero-length bit-fields. Other unnamed bit-fields are real - // storage and classify like named ones, matching GCC. - if (BitField && i->isZeroLengthBitField()) + // Ignore padding bit-fields. + if (BitField && i->isUnnamedBitField()) continue; // AMD64-ABI 3.2.3p2: Rule 1. If the size of an object is larger than @@ -2250,7 +2249,7 @@ void X86_64ABIInfo::classify(QualType Ty, uint64_t OffsetBase, Class &Lo, // structure to be passed in memory even if unaligned, and // therefore they can straddle an eightbyte. if (BitField) { - assert(!i->isZeroLengthBitField()); + assert(!i->isUnnamedBitField()); uint64_t Offset = OffsetBase + Layout.getFieldOffset(idx); uint64_t Size = i->getBitWidthValue(); diff --git a/clang/test/CodeGen/X86/x86_64-arguments.c b/clang/test/CodeGen/X86/x86_64-arguments.c index b56792dd50cdd..580f9487395d3 100644 --- a/clang/test/CodeGen/X86/x86_64-arguments.c +++ b/clang/test/CodeGen/X86/x86_64-arguments.c @@ -590,58 +590,6 @@ _BitInt(128) f74(__uint128_t b, __uint128_t c, __uint128_t d, long e, _BitInt(12 return a; } -// check that non-zero-width unnamed bit-fields classify INTEGER like named -// ones, so a run of (u)int128_t bit-fields is passed and returned as an i128 -struct s75 { - __uint128_t : 124; - __uint128_t a : 4; -}; -// CHECK-LABEL: define{{.*}} i128 @f75() -struct s75 f75(void) { - return (struct s75){0}; -} -// CHECK-LABEL: define{{.*}} void @f76(i128 %a.coerce) -void f76(struct s75 a) { -} - -struct s77 { - __uint128_t a : 4; - __uint128_t : 124; -}; -// CHECK-LABEL: define{{.*}} i128 @f77() -struct s77 f77(void) { - return (struct s77){0}; -} -// CHECK-LABEL: define{{.*}} void @f78(i128 %a.coerce) -void f78(struct s77 a) { -} - -// an unnamed bit-field filling the low eightbyte makes it INTEGER -struct s79 { - long : 64; - long a; -}; -// CHECK-LABEL: define{{.*}} { i64, i64 } @f79() -struct s79 f79(void) { - return (struct s79){0}; -} -// CHECK-LABEL: define{{.*}} void @f80(i64 %a.coerce0, i64 %a.coerce1) -void f80(struct s79 a) { -} - -// an unnamed bit-field in the high eightbyte is INTEGER while the low is SSE -struct s81 { - double d; - int : 32; -}; -// CHECK-LABEL: define{{.*}} { double, i32 } @f81() -struct s81 f81(void) { - return (struct s81){0}; -} -// CHECK-LABEL: define{{.*}} void @f82(double %a.coerce0, i32 %a.coerce1) -void f82(struct s81 a) { -} - /// 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: diff --git a/clang/test/CodeGen/X86/x86_64-union-abi.c b/clang/test/CodeGen/X86/x86_64-union-abi.c index 3bc60464c02a8..a9b5c60f7eeaa 100644 --- a/clang/test/CodeGen/X86/x86_64-union-abi.c +++ b/clang/test/CodeGen/X86/x86_64-union-abi.c @@ -76,22 +76,3 @@ void take_wide_unnamed(union WideUnnamedBitfield u); void call_wide_unnamed(union WideUnnamedBitfield u) { take_wide_unnamed(u); } // CHECK-DAG: declare void @take_wide_unnamed(i64) - -// A non-zero-width unnamed bitfield is INTEGER, which beats the double's SSE -// in the merge, so the union travels in a GPR. -union DoubleUnnamedBitfield { - double d; - long : 64; -}; - -void take_double_unnamed(union DoubleUnnamedBitfield u); -void call_double_unnamed(union DoubleUnnamedBitfield u) { - take_double_unnamed(u); -} - -// CHECK-DAG: declare void @take_double_unnamed(i64) - -union DoubleUnnamedBitfield ret_double_unnamed(void); -void call_ret_double_unnamed(void) { ret_double_unnamed(); } - -// CHECK-DAG: declare i64 @ret_double_unnamed() diff --git a/llvm/lib/ABI/Targets/X86.cpp b/llvm/lib/ABI/Targets/X86.cpp index 88bfb8ad453cc..63045ebe225a6 100644 --- a/llvm/lib/ABI/Targets/X86.cpp +++ b/llvm/lib/ABI/Targets/X86.cpp @@ -557,9 +557,7 @@ void X86_64TargetInfo::classify(const Type *T, uint64_t OffsetBase, Class &Lo, uint64_t Offset = OffsetBase + Field.OffsetInBits; bool BitField = Field.IsBitField; - // Ignore zero-length bit-fields. Other unnamed bit-fields are real - // storage and classify like named ones, matching GCC. - if (BitField && Field.BitFieldWidth == 0) + if (BitField && Field.IsUnnamedBitfield) continue; if (Size > 128 &&