From 341e0f78d1a59e8c9e92016e2ae4ebaabd291d0f Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Sat, 11 Mar 2023 18:36:10 +0000 Subject: Fortify codegen test. --- tests/codegen/slice-init.rs | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) (limited to 'tests/codegen') diff --git a/tests/codegen/slice-init.rs b/tests/codegen/slice-init.rs index 794b773a776..d80628cb1d4 100644 --- a/tests/codegen/slice-init.rs +++ b/tests/codegen/slice-init.rs @@ -8,7 +8,7 @@ pub fn zero_sized_elem() { // CHECK-NOT: br label %repeat_loop_header{{.*}} // CHECK-NOT: call void @llvm.memset.p0 let x = [(); 4]; - drop(&x); + opaque(&x); } // CHECK-LABEL: @zero_len_array @@ -17,7 +17,7 @@ pub fn zero_len_array() { // CHECK-NOT: br label %repeat_loop_header{{.*}} // CHECK-NOT: call void @llvm.memset.p0 let x = [4; 0]; - drop(&x); + opaque(&x); } // CHECK-LABEL: @byte_array @@ -26,7 +26,7 @@ pub fn byte_array() { // CHECK: call void @llvm.memset.{{.+}}({{i8\*|ptr}} {{.*}}, i8 7, i{{[0-9]+}} 4 // CHECK-NOT: br label %repeat_loop_header{{.*}} let x = [7u8; 4]; - drop(&x); + opaque(&x); } #[allow(dead_code)] @@ -42,7 +42,7 @@ pub fn byte_enum_array() { // CHECK: call void @llvm.memset.{{.+}}({{i8\*|ptr}} {{.*}}, i8 {{.*}}, i{{[0-9]+}} 4 // CHECK-NOT: br label %repeat_loop_header{{.*}} let x = [Init::Memset; 4]; - drop(&x); + opaque(&x); } // CHECK-LABEL: @zeroed_integer_array @@ -51,7 +51,7 @@ pub fn zeroed_integer_array() { // CHECK: call void @llvm.memset.{{.+}}({{i8\*|ptr}} {{.*}}, i8 0, i{{[0-9]+}} 16 // CHECK-NOT: br label %repeat_loop_header{{.*}} let x = [0u32; 4]; - drop(&x); + opaque(&x); } // CHECK-LABEL: @nonzero_integer_array @@ -60,5 +60,9 @@ pub fn nonzero_integer_array() { // CHECK: br label %repeat_loop_header{{.*}} // CHECK-NOT: call void @llvm.memset.p0 let x = [0x1a_2b_3c_4d_u32; 4]; - drop(&x); + opaque(&x); } + +// Use an opaque function to prevent rustc from removing useless drops. +#[inline(never)] +pub fn opaque(_: impl Sized) {} -- cgit 1.4.1-3-g733a5 From 4de2d8fb66e5036af00a7a900c72c6ae00ca2cf4 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Sun, 12 Mar 2023 14:10:30 +0000 Subject: Perform reference propagation earlier. --- compiler/rustc_mir_transform/src/lib.rs | 2 +- tests/codegen/slice-ref-equality.rs | 32 ++++++++--------- tests/mir-opt/casts.redundant.InstSimplify.diff | 2 +- tests/mir-opt/copy-prop/mutate_through_pointer.rs | 2 ++ ...est.SimplifyComparisonIntegral.panic-abort.diff | 40 ++++++++++------------ ...st.SimplifyComparisonIntegral.panic-unwind.diff | 40 ++++++++++------------ .../pre-codegen/loops.mapped.PreCodegen.after.mir | 4 ++- .../loops.vec_move.PreCodegen.after.mir | 4 ++- ...inclusive_loop.PreCodegen.after.panic-abort.mir | 2 ++ ...nclusive_loop.PreCodegen.after.panic-unwind.mir | 2 ++ ..._get_mut_usize.PreCodegen.after.panic-abort.mir | 10 +++--- ...get_mut_usize.PreCodegen.after.panic-unwind.mir | 10 +++--- ...cked_mut_range.PreCodegen.after.panic-abort.mir | 2 -- ...ked_mut_range.PreCodegen.after.panic-unwind.mir | 2 -- ...numerated_loop.PreCodegen.after.panic-abort.mir | 4 ++- ...umerated_loop.PreCodegen.after.panic-unwind.mir | 4 ++- ...r.forward_loop.PreCodegen.after.panic-abort.mir | 4 ++- ....forward_loop.PreCodegen.after.panic-unwind.mir | 4 ++- .../spans.outer.PreCodegen.after.panic-abort.mir | 6 ++-- .../spans.outer.PreCodegen.after.panic-unwind.mir | 6 ++-- 20 files changed, 96 insertions(+), 86 deletions(-) (limited to 'tests/codegen') diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs index fa8257cf984..d419329f2d6 100644 --- a/compiler/rustc_mir_transform/src/lib.rs +++ b/compiler/rustc_mir_transform/src/lib.rs @@ -553,6 +553,7 @@ fn run_optimization_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { &normalize_array_len::NormalizeArrayLen, // has to run after `slice::len` lowering &const_goto::ConstGoto, &remove_unneeded_drops::RemoveUnneededDrops, + &ref_prop::ReferencePropagation, &sroa::ScalarReplacementOfAggregates, &match_branches::MatchBranchSimplification, // inst combine is after MatchBranchSimplification to clean up Ne(_1, false) @@ -560,7 +561,6 @@ fn run_optimization_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { &instsimplify::InstSimplify, &simplify::SimplifyLocals::BeforeConstProp, ©_prop::CopyProp, - &ref_prop::ReferencePropagation, // Perform `SeparateConstSwitch` after SSA-based analyses, as cloning blocks may // destroy the SSA property. It should still happen before const-propagation, so the // latter pass will leverage the created opportunities. diff --git a/tests/codegen/slice-ref-equality.rs b/tests/codegen/slice-ref-equality.rs index 8f0adab35e7..c91e5bc3cd0 100644 --- a/tests/codegen/slice-ref-equality.rs +++ b/tests/codegen/slice-ref-equality.rs @@ -44,48 +44,48 @@ pub fn is_zero_array(data: &[u8; 4]) -> bool { // equality for non-byte types also just emit a `bcmp`, not a loop. // CHECK-LABEL: @eq_slice_of_nested_u8( -// CHECK-SAME: [[USIZE:i16|i32|i64]] noundef %1 -// CHECK-SAME: [[USIZE]] noundef %3 +// CHECK-SAME: [[USIZE:i16|i32|i64]] noundef %x.1 +// CHECK-SAME: [[USIZE]] noundef %y.1 #[no_mangle] fn eq_slice_of_nested_u8(x: &[[u8; 3]], y: &[[u8; 3]]) -> bool { - // CHECK: icmp eq [[USIZE]] %1, %3 - // CHECK: %[[BYTES:.+]] = mul nsw [[USIZE]] %1, 3 + // CHECK: icmp eq [[USIZE]] %x.1, %y.1 + // CHECK: %[[BYTES:.+]] = mul nsw [[USIZE]] %x.1, 3 // CHECK: tail call{{( noundef)?}} i32 @{{bcmp|memcmp}}({{i8\*|ptr}} // CHECK-SAME: , [[USIZE]]{{( noundef)?}} %[[BYTES]]) x == y } // CHECK-LABEL: @eq_slice_of_i32( -// CHECK-SAME: [[USIZE:i16|i32|i64]] noundef %1 -// CHECK-SAME: [[USIZE]] noundef %3 +// CHECK-SAME: [[USIZE:i16|i32|i64]] noundef %x.1 +// CHECK-SAME: [[USIZE]] noundef %y.1 #[no_mangle] fn eq_slice_of_i32(x: &[i32], y: &[i32]) -> bool { - // CHECK: icmp eq [[USIZE]] %1, %3 - // CHECK: %[[BYTES:.+]] = shl nsw [[USIZE]] %1, 2 + // CHECK: icmp eq [[USIZE]] %x.1, %y.1 + // CHECK: %[[BYTES:.+]] = shl nsw [[USIZE]] %x.1, 2 // CHECK: tail call{{( noundef)?}} i32 @{{bcmp|memcmp}}({{i32\*|ptr}} // CHECK-SAME: , [[USIZE]]{{( noundef)?}} %[[BYTES]]) x == y } // CHECK-LABEL: @eq_slice_of_nonzero( -// CHECK-SAME: [[USIZE:i16|i32|i64]] noundef %1 -// CHECK-SAME: [[USIZE]] noundef %3 +// CHECK-SAME: [[USIZE:i16|i32|i64]] noundef %x.1 +// CHECK-SAME: [[USIZE]] noundef %y.1 #[no_mangle] fn eq_slice_of_nonzero(x: &[NonZeroU32], y: &[NonZeroU32]) -> bool { - // CHECK: icmp eq [[USIZE]] %1, %3 - // CHECK: %[[BYTES:.+]] = shl nsw [[USIZE]] %1, 2 + // CHECK: icmp eq [[USIZE]] %x.1, %y.1 + // CHECK: %[[BYTES:.+]] = shl nsw [[USIZE]] %x.1, 2 // CHECK: tail call{{( noundef)?}} i32 @{{bcmp|memcmp}}({{i32\*|ptr}} // CHECK-SAME: , [[USIZE]]{{( noundef)?}} %[[BYTES]]) x == y } // CHECK-LABEL: @eq_slice_of_option_of_nonzero( -// CHECK-SAME: [[USIZE:i16|i32|i64]] noundef %1 -// CHECK-SAME: [[USIZE]] noundef %3 +// CHECK-SAME: [[USIZE:i16|i32|i64]] noundef %x.1 +// CHECK-SAME: [[USIZE]] noundef %y.1 #[no_mangle] fn eq_slice_of_option_of_nonzero(x: &[Option], y: &[Option]) -> bool { - // CHECK: icmp eq [[USIZE]] %1, %3 - // CHECK: %[[BYTES:.+]] = shl nsw [[USIZE]] %1, 1 + // CHECK: icmp eq [[USIZE]] %x.1, %y.1 + // CHECK: %[[BYTES:.+]] = shl nsw [[USIZE]] %x.1, 1 // CHECK: tail call{{( noundef)?}} i32 @{{bcmp|memcmp}}({{i16\*|ptr}} // CHECK-SAME: , [[USIZE]]{{( noundef)?}} %[[BYTES]]) x == y diff --git a/tests/mir-opt/casts.redundant.InstSimplify.diff b/tests/mir-opt/casts.redundant.InstSimplify.diff index ff6d11c4596..f5ea78aecbe 100644 --- a/tests/mir-opt/casts.redundant.InstSimplify.diff +++ b/tests/mir-opt/casts.redundant.InstSimplify.diff @@ -7,7 +7,7 @@ let mut _2: *const &u8; let mut _3: *const &u8; scope 1 (inlined generic_cast::<&u8, &u8>) { - debug x => _3; + debug x => _1; } bb0: { diff --git a/tests/mir-opt/copy-prop/mutate_through_pointer.rs b/tests/mir-opt/copy-prop/mutate_through_pointer.rs index da142e33948..753787089b5 100644 --- a/tests/mir-opt/copy-prop/mutate_through_pointer.rs +++ b/tests/mir-opt/copy-prop/mutate_through_pointer.rs @@ -1,3 +1,5 @@ +// unit-test: CopyProp +// // This attempts to mutate `a` via a pointer derived from `addr_of!(a)`. That is UB // according to Miri. However, the decision to make this UB - and to allow // rustc to rely on that fact for the purpose of optimizations - has not been diff --git a/tests/mir-opt/issue_76432.test.SimplifyComparisonIntegral.panic-abort.diff b/tests/mir-opt/issue_76432.test.SimplifyComparisonIntegral.panic-abort.diff index 1cc44ce06cf..b647455aeec 100644 --- a/tests/mir-opt/issue_76432.test.SimplifyComparisonIntegral.panic-abort.diff +++ b/tests/mir-opt/issue_76432.test.SimplifyComparisonIntegral.panic-abort.diff @@ -6,20 +6,16 @@ let mut _0: (); let _2: &[T]; let mut _3: &[T; 3]; - let _4: &[T; 3]; - let _5: [T; 3]; + let _4: [T; 3]; + let mut _5: T; let mut _6: T; let mut _7: T; - let mut _8: T; + let mut _8: usize; let mut _9: usize; - let mut _10: usize; - let mut _11: bool; - let mut _15: !; + let mut _10: bool; + let mut _11: !; scope 1 { debug v => _2; - let _12: &T; - let _13: &T; - let _14: &T; scope 2 { debug v1 => &(*_2)[0 of 3]; debug v2 => &(*_2)[1 of 3]; @@ -28,26 +24,26 @@ } bb0: { - StorageLive(_2); - StorageLive(_5); - _5 = [_1, _1, _1]; - _4 = &_5; - _2 = _4 as &[T] (PointerCoercion(Unsize)); - _9 = Len((*_2)); - _10 = const 3_usize; -- _11 = Eq(move _9, const 3_usize); -- switchInt(move _11) -> [0: bb1, otherwise: bb2]; + StorageLive(_3); + StorageLive(_4); + _4 = [_1, _1, _1]; + _3 = &_4; + _2 = move _3 as &[T] (PointerCoercion(Unsize)); + StorageDead(_3); + _8 = Len((*_2)); + _9 = const 3_usize; +- _10 = Eq(move _8, const 3_usize); +- switchInt(move _10) -> [0: bb1, otherwise: bb2]; + nop; -+ switchInt(move _9) -> [3: bb2, otherwise: bb1]; ++ switchInt(move _8) -> [3: bb2, otherwise: bb1]; } bb1: { - _15 = core::panicking::panic(const "internal error: entered unreachable code") -> unwind unreachable; + _11 = core::panicking::panic(const "internal error: entered unreachable code") -> unwind unreachable; } bb2: { - StorageDead(_5); - StorageDead(_2); + StorageDead(_4); return; } } diff --git a/tests/mir-opt/issue_76432.test.SimplifyComparisonIntegral.panic-unwind.diff b/tests/mir-opt/issue_76432.test.SimplifyComparisonIntegral.panic-unwind.diff index b708f667438..b02be61d031 100644 --- a/tests/mir-opt/issue_76432.test.SimplifyComparisonIntegral.panic-unwind.diff +++ b/tests/mir-opt/issue_76432.test.SimplifyComparisonIntegral.panic-unwind.diff @@ -6,20 +6,16 @@ let mut _0: (); let _2: &[T]; let mut _3: &[T; 3]; - let _4: &[T; 3]; - let _5: [T; 3]; + let _4: [T; 3]; + let mut _5: T; let mut _6: T; let mut _7: T; - let mut _8: T; + let mut _8: usize; let mut _9: usize; - let mut _10: usize; - let mut _11: bool; - let mut _15: !; + let mut _10: bool; + let mut _11: !; scope 1 { debug v => _2; - let _12: &T; - let _13: &T; - let _14: &T; scope 2 { debug v1 => &(*_2)[0 of 3]; debug v2 => &(*_2)[1 of 3]; @@ -28,26 +24,26 @@ } bb0: { - StorageLive(_2); - StorageLive(_5); - _5 = [_1, _1, _1]; - _4 = &_5; - _2 = _4 as &[T] (PointerCoercion(Unsize)); - _9 = Len((*_2)); - _10 = const 3_usize; -- _11 = Eq(move _9, const 3_usize); -- switchInt(move _11) -> [0: bb1, otherwise: bb2]; + StorageLive(_3); + StorageLive(_4); + _4 = [_1, _1, _1]; + _3 = &_4; + _2 = move _3 as &[T] (PointerCoercion(Unsize)); + StorageDead(_3); + _8 = Len((*_2)); + _9 = const 3_usize; +- _10 = Eq(move _8, const 3_usize); +- switchInt(move _10) -> [0: bb1, otherwise: bb2]; + nop; -+ switchInt(move _9) -> [3: bb2, otherwise: bb1]; ++ switchInt(move _8) -> [3: bb2, otherwise: bb1]; } bb1: { - _15 = core::panicking::panic(const "internal error: entered unreachable code") -> unwind continue; + _11 = core::panicking::panic(const "internal error: entered unreachable code") -> unwind continue; } bb2: { - StorageDead(_5); - StorageDead(_2); + StorageDead(_4); return; } } diff --git a/tests/mir-opt/pre-codegen/loops.mapped.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/loops.mapped.PreCodegen.after.mir index e4e1d052e73..2614160363e 100644 --- a/tests/mir-opt/pre-codegen/loops.mapped.PreCodegen.after.mir +++ b/tests/mir-opt/pre-codegen/loops.mapped.PreCodegen.after.mir @@ -38,11 +38,13 @@ fn mapped(_1: impl Iterator, _2: impl Fn(T) -> U) -> () { bb2: { StorageLive(_7); + StorageLive(_6); _6 = &mut _5; - _7 = , impl Fn(T) -> U> as Iterator>::next(_6) -> [return: bb3, unwind: bb9]; + _7 = , impl Fn(T) -> U> as Iterator>::next(move _6) -> [return: bb3, unwind: bb9]; } bb3: { + StorageDead(_6); _8 = discriminant(_7); switchInt(move _8) -> [0: bb4, 1: bb6, otherwise: bb8]; } diff --git a/tests/mir-opt/pre-codegen/loops.vec_move.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/loops.vec_move.PreCodegen.after.mir index 1b5f2a0884b..8eff46fb931 100644 --- a/tests/mir-opt/pre-codegen/loops.vec_move.PreCodegen.after.mir +++ b/tests/mir-opt/pre-codegen/loops.vec_move.PreCodegen.after.mir @@ -30,11 +30,13 @@ fn vec_move(_1: Vec) -> () { bb2: { StorageLive(_5); + StorageLive(_4); _4 = &mut _3; - _5 = as Iterator>::next(_4) -> [return: bb3, unwind: bb9]; + _5 = as Iterator>::next(move _4) -> [return: bb3, unwind: bb9]; } bb3: { + StorageDead(_4); _6 = discriminant(_5); switchInt(move _6) -> [0: bb4, 1: bb6, otherwise: bb8]; } diff --git a/tests/mir-opt/pre-codegen/range_iter.inclusive_loop.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/range_iter.inclusive_loop.PreCodegen.after.panic-abort.mir index 9737c9a87c7..8d306858b43 100644 --- a/tests/mir-opt/pre-codegen/range_iter.inclusive_loop.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/range_iter.inclusive_loop.PreCodegen.after.panic-abort.mir @@ -40,11 +40,13 @@ fn inclusive_loop(_1: u32, _2: u32, _3: impl Fn(u32)) -> () { bb1: { StorageLive(_7); + StorageLive(_6); _6 = &mut _5; _7 = as iter::range::RangeInclusiveIteratorImpl>::spec_next(_6) -> [return: bb2, unwind unreachable]; } bb2: { + StorageDead(_6); _8 = discriminant(_7); switchInt(move _8) -> [0: bb3, 1: bb5, otherwise: bb7]; } diff --git a/tests/mir-opt/pre-codegen/range_iter.inclusive_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/range_iter.inclusive_loop.PreCodegen.after.panic-unwind.mir index 04d6da1d9bd..e92c054c838 100644 --- a/tests/mir-opt/pre-codegen/range_iter.inclusive_loop.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/range_iter.inclusive_loop.PreCodegen.after.panic-unwind.mir @@ -40,11 +40,13 @@ fn inclusive_loop(_1: u32, _2: u32, _3: impl Fn(u32)) -> () { bb1: { StorageLive(_7); + StorageLive(_6); _6 = &mut _5; _7 = as iter::range::RangeInclusiveIteratorImpl>::spec_next(_6) -> [return: bb2, unwind: bb8]; } bb2: { + StorageDead(_6); _8 = discriminant(_7); switchInt(move _8) -> [0: bb3, 1: bb5, otherwise: bb7]; } diff --git a/tests/mir-opt/pre-codegen/slice_index.slice_get_mut_usize.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_index.slice_get_mut_usize.PreCodegen.after.panic-abort.mir index 602f8652949..07a58309ee4 100644 --- a/tests/mir-opt/pre-codegen/slice_index.slice_get_mut_usize.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/slice_index.slice_get_mut_usize.PreCodegen.after.panic-abort.mir @@ -53,7 +53,7 @@ fn slice_get_mut_usize(_1: &mut [u32], _2: usize) -> Option<&mut u32> { } bb0: { - StorageLive(_8); + StorageLive(_7); StorageLive(_4); StorageLive(_3); _3 = Len((*_1)); @@ -68,7 +68,7 @@ fn slice_get_mut_usize(_1: &mut [u32], _2: usize) -> Option<&mut u32> { } bb2: { - StorageLive(_7); + StorageLive(_8); StorageLive(_5); _5 = &raw mut (*_1); StorageLive(_9); @@ -79,14 +79,14 @@ fn slice_get_mut_usize(_1: &mut [u32], _2: usize) -> Option<&mut u32> { StorageDead(_9); StorageDead(_5); _8 = &mut (*_7); - _0 = Option::<&mut u32>::Some(_8); - StorageDead(_7); + _0 = Option::<&mut u32>::Some(move _8); + StorageDead(_8); goto -> bb3; } bb3: { StorageDead(_4); - StorageDead(_8); + StorageDead(_7); return; } } diff --git a/tests/mir-opt/pre-codegen/slice_index.slice_get_mut_usize.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_index.slice_get_mut_usize.PreCodegen.after.panic-unwind.mir index 602f8652949..07a58309ee4 100644 --- a/tests/mir-opt/pre-codegen/slice_index.slice_get_mut_usize.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/slice_index.slice_get_mut_usize.PreCodegen.after.panic-unwind.mir @@ -53,7 +53,7 @@ fn slice_get_mut_usize(_1: &mut [u32], _2: usize) -> Option<&mut u32> { } bb0: { - StorageLive(_8); + StorageLive(_7); StorageLive(_4); StorageLive(_3); _3 = Len((*_1)); @@ -68,7 +68,7 @@ fn slice_get_mut_usize(_1: &mut [u32], _2: usize) -> Option<&mut u32> { } bb2: { - StorageLive(_7); + StorageLive(_8); StorageLive(_5); _5 = &raw mut (*_1); StorageLive(_9); @@ -79,14 +79,14 @@ fn slice_get_mut_usize(_1: &mut [u32], _2: usize) -> Option<&mut u32> { StorageDead(_9); StorageDead(_5); _8 = &mut (*_7); - _0 = Option::<&mut u32>::Some(_8); - StorageDead(_7); + _0 = Option::<&mut u32>::Some(move _8); + StorageDead(_8); goto -> bb3; } bb3: { StorageDead(_4); - StorageDead(_8); + StorageDead(_7); return; } } diff --git a/tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.panic-abort.mir index e07e2bb7bfe..2f5d356a26d 100644 --- a/tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.panic-abort.mir @@ -61,7 +61,6 @@ fn slice_get_unchecked_mut_range(_1: &mut [u32], _2: std::ops::Range) -> bb0: { _3 = move (_2.0: usize); _4 = move (_2.1: usize); - StorageLive(_13); StorageLive(_5); _5 = &raw mut (*_1); StorageLive(_14); @@ -92,7 +91,6 @@ fn slice_get_unchecked_mut_range(_1: &mut [u32], _2: std::ops::Range) -> StorageDead(_15); StorageDead(_5); _0 = &mut (*_13); - StorageDead(_13); return; } } diff --git a/tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.panic-unwind.mir index e07e2bb7bfe..2f5d356a26d 100644 --- a/tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.panic-unwind.mir @@ -61,7 +61,6 @@ fn slice_get_unchecked_mut_range(_1: &mut [u32], _2: std::ops::Range) -> bb0: { _3 = move (_2.0: usize); _4 = move (_2.1: usize); - StorageLive(_13); StorageLive(_5); _5 = &raw mut (*_1); StorageLive(_14); @@ -92,7 +91,6 @@ fn slice_get_unchecked_mut_range(_1: &mut [u32], _2: std::ops::Range) -> StorageDead(_15); StorageDead(_5); _0 = &mut (*_13); - StorageDead(_13); return; } } diff --git a/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-abort.mir index d1ab16697a6..2cf81d86267 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-abort.mir @@ -152,11 +152,13 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { bb4: { StorageLive(_17); + StorageLive(_16); _16 = &mut _15; - _17 = > as Iterator>::next(_16) -> [return: bb5, unwind unreachable]; + _17 = > as Iterator>::next(move _16) -> [return: bb5, unwind unreachable]; } bb5: { + StorageDead(_16); _18 = discriminant(_17); switchInt(move _18) -> [0: bb6, 1: bb8, otherwise: bb10]; } diff --git a/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-unwind.mir index 03751f7fdf7..6985806ec93 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-unwind.mir @@ -152,11 +152,13 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { bb4: { StorageLive(_17); + StorageLive(_16); _16 = &mut _15; - _17 = > as Iterator>::next(_16) -> [return: bb5, unwind: bb11]; + _17 = > as Iterator>::next(move _16) -> [return: bb5, unwind: bb11]; } bb5: { + StorageDead(_16); _18 = discriminant(_17); switchInt(move _18) -> [0: bb6, 1: bb8, otherwise: bb10]; } diff --git a/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-abort.mir index db971e10f32..a4b8460e98e 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-abort.mir @@ -140,11 +140,13 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () { bb4: { StorageLive(_16); + StorageLive(_15); _15 = &mut _14; - _16 = as Iterator>::next(_15) -> [return: bb5, unwind unreachable]; + _16 = as Iterator>::next(move _15) -> [return: bb5, unwind unreachable]; } bb5: { + StorageDead(_15); _17 = discriminant(_16); switchInt(move _17) -> [0: bb6, 1: bb8, otherwise: bb10]; } diff --git a/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-unwind.mir index 74597799168..58f312b1aac 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-unwind.mir @@ -140,11 +140,13 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () { bb4: { StorageLive(_16); + StorageLive(_15); _15 = &mut _14; - _16 = as Iterator>::next(_15) -> [return: bb5, unwind: bb11]; + _16 = as Iterator>::next(move _15) -> [return: bb5, unwind: bb11]; } bb5: { + StorageDead(_15); _17 = discriminant(_16); switchInt(move _17) -> [0: bb6, 1: bb8, otherwise: bb10]; } diff --git a/tests/mir-opt/pre-codegen/spans.outer.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/spans.outer.PreCodegen.after.panic-abort.mir index b9329520bab..ed7107e53ef 100644 --- a/tests/mir-opt/pre-codegen/spans.outer.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/spans.outer.PreCodegen.after.panic-abort.mir @@ -3,17 +3,19 @@ fn outer(_1: u8) -> u8 { debug v => _1; // in scope 0 at $DIR/spans.rs:10:14: 10:15 let mut _0: u8; // return place in scope 0 at $DIR/spans.rs:10:24: 10:26 - let _2: &u8; // in scope 0 at $DIR/spans.rs:11:11: 11:13 + let mut _2: &u8; // in scope 0 at $DIR/spans.rs:11:11: 11:13 bb0: { + StorageLive(_2); // scope 0 at $DIR/spans.rs:11:11: 11:13 _2 = &_1; // scope 0 at $DIR/spans.rs:11:11: 11:13 - _0 = inner(_2) -> [return: bb1, unwind unreachable]; // scope 0 at $DIR/spans.rs:11:5: 11:14 + _0 = inner(move _2) -> [return: bb1, unwind unreachable]; // scope 0 at $DIR/spans.rs:11:5: 11:14 // mir::Constant // + span: $DIR/spans.rs:11:5: 11:10 // + literal: Const { ty: for<'a> fn(&'a u8) -> u8 {inner}, val: Value() } } bb1: { + StorageDead(_2); // scope 0 at $DIR/spans.rs:11:13: 11:14 return; // scope 0 at $DIR/spans.rs:12:2: 12:2 } } diff --git a/tests/mir-opt/pre-codegen/spans.outer.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/spans.outer.PreCodegen.after.panic-unwind.mir index 1e20b1be56b..dc436dc2650 100644 --- a/tests/mir-opt/pre-codegen/spans.outer.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/spans.outer.PreCodegen.after.panic-unwind.mir @@ -3,17 +3,19 @@ fn outer(_1: u8) -> u8 { debug v => _1; // in scope 0 at $DIR/spans.rs:10:14: 10:15 let mut _0: u8; // return place in scope 0 at $DIR/spans.rs:10:24: 10:26 - let _2: &u8; // in scope 0 at $DIR/spans.rs:11:11: 11:13 + let mut _2: &u8; // in scope 0 at $DIR/spans.rs:11:11: 11:13 bb0: { + StorageLive(_2); // scope 0 at $DIR/spans.rs:11:11: 11:13 _2 = &_1; // scope 0 at $DIR/spans.rs:11:11: 11:13 - _0 = inner(_2) -> [return: bb1, unwind continue]; // scope 0 at $DIR/spans.rs:11:5: 11:14 + _0 = inner(move _2) -> [return: bb1, unwind continue]; // scope 0 at $DIR/spans.rs:11:5: 11:14 // mir::Constant // + span: $DIR/spans.rs:11:5: 11:10 // + literal: Const { ty: for<'a> fn(&'a u8) -> u8 {inner}, val: Value() } } bb1: { + StorageDead(_2); // scope 0 at $DIR/spans.rs:11:13: 11:14 return; // scope 0 at $DIR/spans.rs:12:2: 12:2 } } -- cgit 1.4.1-3-g733a5 From 0becc89d4a75d14571b02fb34ec1e3a45c9fb9dc Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Mon, 31 Oct 2022 20:38:40 -0700 Subject: rustc_target: Add alignment to indirectly-passed by-value types, correcting the alignment of `byval` on x86 in the process. Commit 88e4d2c2918428d55e34cd57c11279ea839c8822 from five years ago removed support for alignment on indirectly-passed arguments because of problems with the `i686-pc-windows-msvc` target. Unfortunately, the `memcpy` optimizations I recently added to LLVM 16 depend on this to forward `memcpy`s. This commit attempts to fix the problems with `byval` parameters on that target and now correctly adds the `align` attribute. The problem is summarized in [this comment] by @eddyb. Briefly, 32-bit x86 has special alignment rules for `byval` parameters: for the most part, their alignment is forced to 4. This is not well-documented anywhere but in the Clang source. I looked at the logic in Clang `TargetInfo.cpp` and tried to replicate it here. The relevant methods in that file are `X86_32ABIInfo::getIndirectResult()` and `X86_32ABIInfo::getTypeStackAlignInBytes()`. The `align` parameter attribute for `byval` parameters in LLVM must match the platform ABI, or miscompilations will occur. Note that this doesn't use the approach suggested by eddyb, because I felt it was overkill to store the alignment in `on_stack` when special handling is really only needed for 32-bit x86. As a side effect, this should fix #80127, because it will make the `align` parameter attribute for `byval` parameters match the platform ABI on LLVM x86-64. [this comment]: https://github.com/rust-lang/rust/pull/80822#issuecomment-829985417 --- compiler/rustc_target/src/abi/call/m68k.rs | 2 +- compiler/rustc_target/src/abi/call/mod.rs | 19 +++++--- compiler/rustc_target/src/abi/call/wasm.rs | 2 +- compiler/rustc_target/src/abi/call/x86.rs | 35 ++++++++++++-- compiler/rustc_target/src/abi/call/x86_64.rs | 2 +- tests/codegen/align-byval.rs | 56 ++++++++++++++++++++++ tests/codegen/function-arguments-noopt.rs | 4 +- tests/codegen/function-arguments.rs | 4 +- tests/run-make/extern-fn-explicit-align/Makefile | 5 ++ tests/run-make/extern-fn-explicit-align/test.c | 35 ++++++++++++++ tests/run-make/extern-fn-explicit-align/test.rs | 61 ++++++++++++++++++++++++ 11 files changed, 208 insertions(+), 17 deletions(-) create mode 100644 tests/codegen/align-byval.rs create mode 100644 tests/run-make/extern-fn-explicit-align/Makefile create mode 100644 tests/run-make/extern-fn-explicit-align/test.c create mode 100644 tests/run-make/extern-fn-explicit-align/test.rs (limited to 'tests/codegen') diff --git a/compiler/rustc_target/src/abi/call/m68k.rs b/compiler/rustc_target/src/abi/call/m68k.rs index c1e0f54af5f..1d4649ed867 100644 --- a/compiler/rustc_target/src/abi/call/m68k.rs +++ b/compiler/rustc_target/src/abi/call/m68k.rs @@ -10,7 +10,7 @@ fn classify_ret(ret: &mut ArgAbi<'_, Ty>) { fn classify_arg(arg: &mut ArgAbi<'_, Ty>) { if arg.layout.is_aggregate() { - arg.make_indirect_byval(); + arg.make_indirect_byval(None); } else { arg.extend_integer_width_to(32); } diff --git a/compiler/rustc_target/src/abi/call/mod.rs b/compiler/rustc_target/src/abi/call/mod.rs index c4abf6f4b5e..c4984936cac 100644 --- a/compiler/rustc_target/src/abi/call/mod.rs +++ b/compiler/rustc_target/src/abi/call/mod.rs @@ -494,9 +494,7 @@ impl<'a, Ty> ArgAbi<'a, Ty> { .set(ArgAttribute::NonNull) .set(ArgAttribute::NoUndef); attrs.pointee_size = layout.size; - // FIXME(eddyb) We should be doing this, but at least on - // i686-pc-windows-msvc, it results in wrong stack offsets. - // attrs.pointee_align = Some(layout.align.abi); + attrs.pointee_align = Some(layout.align.abi); let extra_attrs = layout.is_unsized().then_some(ArgAttributes::new()); @@ -513,11 +511,19 @@ impl<'a, Ty> ArgAbi<'a, Ty> { self.mode = Self::indirect_pass_mode(&self.layout); } - pub fn make_indirect_byval(&mut self) { + pub fn make_indirect_byval(&mut self, byval_align: Option) { self.make_indirect(); match self.mode { - PassMode::Indirect { attrs: _, extra_attrs: _, ref mut on_stack } => { + PassMode::Indirect { ref mut attrs, extra_attrs: _, ref mut on_stack } => { *on_stack = true; + + // Some platforms, like 32-bit x86, change the alignment of the type when passing + // `byval`. Account for that. + if let Some(byval_align) = byval_align { + // On all targets with byval align this is currently true, so let's assert it. + debug_assert!(byval_align >= Align::from_bytes(4).unwrap()); + attrs.pointee_align = Some(byval_align); + } } _ => unreachable!(), } @@ -644,7 +650,8 @@ impl<'a, Ty> FnAbi<'a, Ty> { { if abi == spec::abi::Abi::X86Interrupt { if let Some(arg) = self.args.first_mut() { - arg.make_indirect_byval(); + // FIXME(pcwalton): This probably should use the x86 `byval` ABI... + arg.make_indirect_byval(None); } return Ok(()); } diff --git a/compiler/rustc_target/src/abi/call/wasm.rs b/compiler/rustc_target/src/abi/call/wasm.rs index 44427ee5317..0eb2309ecb2 100644 --- a/compiler/rustc_target/src/abi/call/wasm.rs +++ b/compiler/rustc_target/src/abi/call/wasm.rs @@ -36,7 +36,7 @@ where { arg.extend_integer_width_to(32); if arg.layout.is_aggregate() && !unwrap_trivial_aggregate(cx, arg) { - arg.make_indirect_byval(); + arg.make_indirect_byval(None); } } diff --git a/compiler/rustc_target/src/abi/call/x86.rs b/compiler/rustc_target/src/abi/call/x86.rs index 7c26335dcf4..58c0717b7d1 100644 --- a/compiler/rustc_target/src/abi/call/x86.rs +++ b/compiler/rustc_target/src/abi/call/x86.rs @@ -1,5 +1,5 @@ use crate::abi::call::{ArgAttribute, FnAbi, PassMode, Reg, RegKind}; -use crate::abi::{HasDataLayout, TyAbiInterface}; +use crate::abi::{Align, HasDataLayout, TyAbiInterface}; use crate::spec::HasTargetSpec; #[derive(PartialEq)] @@ -53,11 +53,38 @@ where if arg.is_ignore() { continue; } - if arg.layout.is_aggregate() { - arg.make_indirect_byval(); - } else { + if !arg.layout.is_aggregate() { arg.extend_integer_width_to(32); + continue; } + + // We need to compute the alignment of the `byval` argument. The rules can be found in + // `X86_32ABIInfo::getTypeStackAlignInBytes` in Clang's `TargetInfo.cpp`. Summarized here, + // they are: + // + // 1. If the natural alignment of the type is less than or equal to 4, the alignment is 4. + // + // 2. Otherwise, on Linux, the alignment of any vector type is the natural alignment. + // (This doesn't matter here because we ensure we have an aggregate with the check above.) + // + // 3. Otherwise, on Apple platforms, the alignment of anything that contains a vector type + // is 16. + // + // 4. If none of these conditions are true, the alignment is 4. + let t = cx.target_spec(); + let align_4 = Align::from_bytes(4).unwrap(); + let align_16 = Align::from_bytes(16).unwrap(); + let byval_align = if arg.layout.align.abi < align_4 { + align_4 + } else if t.is_like_osx && arg.layout.align.abi >= align_16 { + // FIXME(pcwalton): This is dubious--we should actually be looking inside the type to + // determine if it contains SIMD vector values--but I think it's fine? + align_16 + } else { + align_4 + }; + + arg.make_indirect_byval(Some(byval_align)); } if flavor == Flavor::FastcallOrVectorcall { diff --git a/compiler/rustc_target/src/abi/call/x86_64.rs b/compiler/rustc_target/src/abi/call/x86_64.rs index b1aefaf0507..d1efe977699 100644 --- a/compiler/rustc_target/src/abi/call/x86_64.rs +++ b/compiler/rustc_target/src/abi/call/x86_64.rs @@ -213,7 +213,7 @@ where match cls_or_mem { Err(Memory) => { if is_arg { - arg.make_indirect_byval(); + arg.make_indirect_byval(None); } else { // `sret` parameter thus one less integer register available arg.make_indirect(); diff --git a/tests/codegen/align-byval.rs b/tests/codegen/align-byval.rs new file mode 100644 index 00000000000..35b3b1adc2c --- /dev/null +++ b/tests/codegen/align-byval.rs @@ -0,0 +1,56 @@ +// ignore-x86 +// ignore-aarch64 +// ignore-aarch64_be +// ignore-arm +// ignore-armeb +// ignore-avr +// ignore-bpfel +// ignore-bpfeb +// ignore-hexagon +// ignore-mips +// ignore-mips64 +// ignore-msp430 +// ignore-powerpc64 +// ignore-powerpc64le +// ignore-powerpc +// ignore-r600 +// ignore-amdgcn +// ignore-sparc +// ignore-sparcv9 +// ignore-sparcel +// ignore-s390x +// ignore-tce +// ignore-thumb +// ignore-thumbeb +// ignore-xcore +// ignore-nvptx +// ignore-nvptx64 +// ignore-le32 +// ignore-le64 +// ignore-amdil +// ignore-amdil64 +// ignore-hsail +// ignore-hsail64 +// ignore-spir +// ignore-spir64 +// ignore-kalimba +// ignore-shave +// +// Tests that `byval` alignment is properly specified (#80127). +// The only targets that use `byval` are m68k, wasm, x86-64, and x86. Note that +// x86 has special rules (see #103830), and it's therefore ignored here. + +#[repr(C)] +#[repr(align(16))] +struct Foo { + a: [i32; 16], +} + +extern "C" { + // CHECK: declare void @f({{.*}}byval(%Foo) align 16{{.*}}) + fn f(foo: Foo); +} + +pub fn main() { + unsafe { f(Foo { a: [1; 16] }) } +} diff --git a/tests/codegen/function-arguments-noopt.rs b/tests/codegen/function-arguments-noopt.rs index 35f31eba3b1..f99cc8fb415 100644 --- a/tests/codegen/function-arguments-noopt.rs +++ b/tests/codegen/function-arguments-noopt.rs @@ -42,7 +42,7 @@ pub fn borrow_call(x: &i32, f: fn(&i32) -> &i32) -> &i32 { f(x) } -// CHECK: void @struct_({{%S\*|ptr}} sret(%S){{( %_0)?}}, {{%S\*|ptr}} %x) +// CHECK: void @struct_({{%S\*|ptr}} sret(%S) align 4{{( %_0)?}}, {{%S\*|ptr}} align 4 %x) #[no_mangle] pub fn struct_(x: S) -> S { x @@ -51,7 +51,7 @@ pub fn struct_(x: S) -> S { // CHECK-LABEL: @struct_call #[no_mangle] pub fn struct_call(x: S, f: fn(S) -> S) -> S { - // CHECK: call void %f({{%S\*|ptr}} sret(%S){{( %_0)?}}, {{%S\*|ptr}} %{{.+}}) + // CHECK: call void %f({{%S\*|ptr}} sret(%S) align 4{{( %_0)?}}, {{%S\*|ptr}} align 4 %{{.+}}) f(x) } diff --git a/tests/codegen/function-arguments.rs b/tests/codegen/function-arguments.rs index ccf4a5de327..2f047f10311 100644 --- a/tests/codegen/function-arguments.rs +++ b/tests/codegen/function-arguments.rs @@ -142,7 +142,7 @@ pub fn mutable_notunpin_borrow(_: &mut NotUnpin) { pub fn notunpin_borrow(_: &NotUnpin) { } -// CHECK: @indirect_struct({{%S\*|ptr}} noalias nocapture noundef readonly dereferenceable(32) %_1) +// CHECK: @indirect_struct({{%S\*|ptr}} noalias nocapture noundef readonly align 4 dereferenceable(32) %_1) #[no_mangle] pub fn indirect_struct(_: S) { } @@ -188,7 +188,7 @@ pub fn notunpin_box(x: Box) -> Box { x } -// CHECK: @struct_return({{%S\*|ptr}} noalias nocapture noundef sret(%S) dereferenceable(32){{( %_0)?}}) +// CHECK: @struct_return({{%S\*|ptr}} noalias nocapture noundef sret(%S) align 4 dereferenceable(32){{( %_0)?}}) #[no_mangle] pub fn struct_return() -> S { S { diff --git a/tests/run-make/extern-fn-explicit-align/Makefile b/tests/run-make/extern-fn-explicit-align/Makefile new file mode 100644 index 00000000000..4f5d026f213 --- /dev/null +++ b/tests/run-make/extern-fn-explicit-align/Makefile @@ -0,0 +1,5 @@ +include ../tools.mk + +all: $(call NATIVE_STATICLIB,test) + $(RUSTC) test.rs + $(call RUN,test) || exit 1 diff --git a/tests/run-make/extern-fn-explicit-align/test.c b/tests/run-make/extern-fn-explicit-align/test.c new file mode 100644 index 00000000000..a015fc9aaf6 --- /dev/null +++ b/tests/run-make/extern-fn-explicit-align/test.c @@ -0,0 +1,35 @@ +#include +#include +#include +#include + +struct TwoU64s +{ + uint64_t a; + uint64_t b; +} __attribute__((aligned(16))); + +struct BoolAndU32 +{ + bool a; + uint32_t b; +}; + +int32_t many_args( + void *a, + void *b, + const char *c, + uint64_t d, + bool e, + struct BoolAndU32 f, + void *g, + struct TwoU64s h, + void *i, + void *j, + void *k, + void *l, + const char *m) +{ + assert(strcmp(m, "Hello world") == 0); + return 0; +} diff --git a/tests/run-make/extern-fn-explicit-align/test.rs b/tests/run-make/extern-fn-explicit-align/test.rs new file mode 100644 index 00000000000..ba6cc87bd18 --- /dev/null +++ b/tests/run-make/extern-fn-explicit-align/test.rs @@ -0,0 +1,61 @@ +// Issue #80127: Passing structs via FFI should work with explicit alignment. + +use std::ffi::CString; +use std::ptr::null_mut; + +#[derive(Clone, Copy, Debug, PartialEq)] +#[repr(C)] +#[repr(align(16))] +pub struct TwoU64s { + pub a: u64, + pub b: u64, +} + +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct BoolAndU32 { + pub a: bool, + pub b: u32, +} + +#[link(name = "test", kind = "static")] +extern "C" { + fn many_args( + a: *mut (), + b: *mut (), + c: *const i8, + d: u64, + e: bool, + f: BoolAndU32, + g: *mut (), + h: TwoU64s, + i: *mut (), + j: *mut (), + k: *mut (), + l: *mut (), + m: *const i8, + ) -> i32; +} + +fn main() { + let two_u64s = TwoU64s { a: 1, b: 2 }; + let bool_and_u32 = BoolAndU32 { a: true, b: 3 }; + let string = CString::new("Hello world").unwrap(); + unsafe { + many_args( + null_mut(), + null_mut(), + null_mut(), + 4, + true, + bool_and_u32, + null_mut(), + two_u64s, + null_mut(), + null_mut(), + null_mut(), + null_mut(), + string.as_ptr(), + ); + } +} -- cgit 1.4.1-3-g733a5 From 102292655b896135be2970cc9b47b26ec3edea55 Mon Sep 17 00:00:00 2001 From: Erik Desjardins Date: Sat, 13 May 2023 21:54:54 -0400 Subject: align-byval test: use revisions to test different targets --- tests/codegen/align-byval.rs | 75 +++++++++++++++++++++----------------------- 1 file changed, 35 insertions(+), 40 deletions(-) (limited to 'tests/codegen') diff --git a/tests/codegen/align-byval.rs b/tests/codegen/align-byval.rs index 35b3b1adc2c..4315c3371e1 100644 --- a/tests/codegen/align-byval.rs +++ b/tests/codegen/align-byval.rs @@ -1,56 +1,51 @@ -// ignore-x86 -// ignore-aarch64 -// ignore-aarch64_be -// ignore-arm -// ignore-armeb -// ignore-avr -// ignore-bpfel -// ignore-bpfeb -// ignore-hexagon -// ignore-mips -// ignore-mips64 -// ignore-msp430 -// ignore-powerpc64 -// ignore-powerpc64le -// ignore-powerpc -// ignore-r600 -// ignore-amdgcn -// ignore-sparc -// ignore-sparcv9 -// ignore-sparcel -// ignore-s390x -// ignore-tce -// ignore-thumb -// ignore-thumbeb -// ignore-xcore -// ignore-nvptx -// ignore-nvptx64 -// ignore-le32 -// ignore-le64 -// ignore-amdil -// ignore-amdil64 -// ignore-hsail -// ignore-hsail64 -// ignore-spir -// ignore-spir64 -// ignore-kalimba -// ignore-shave -// +// revisions:m68k wasm x86_64-linux x86_64-windows + +//[m68k] compile-flags: --target m68k-unknown-linux-gnu +//[m68k] needs-llvm-components: m68k +//[wasm] compile-flags: --target wasm32-unknown-emscripten +//[wasm] needs-llvm-components: webassembly +//[x86_64-linux] compile-flags: --target x86_64-unknown-linux-gnu +//[x86_64-linux] needs-llvm-components: x86 +//[x86_64-windows] compile-flags: --target x86_64-pc-windows-msvc +//[x86_64-windows] needs-llvm-components: x86 + // Tests that `byval` alignment is properly specified (#80127). // The only targets that use `byval` are m68k, wasm, x86-64, and x86. Note that // x86 has special rules (see #103830), and it's therefore ignored here. +// Note also that Windows mandates a by-ref ABI here, so it does not use byval. + +#![feature(no_core, lang_items)] +#![crate_type = "lib"] +#![no_std] +#![no_core] + +#[lang="sized"] trait Sized { } +#[lang="freeze"] trait Freeze { } +#[lang="copy"] trait Copy { } + +impl Copy for i32 {} +impl Copy for i64 {} #[repr(C)] #[repr(align(16))] struct Foo { a: [i32; 16], + b: i8 } extern "C" { - // CHECK: declare void @f({{.*}}byval(%Foo) align 16{{.*}}) + // m68k: declare void @f({{.*}}byval(%Foo) align 16{{.*}}) + + // wasm: declare void @f({{.*}}byval(%Foo) align 16{{.*}}) + + // x86_64-linux: declare void @f({{.*}}byval(%Foo) align 16{{.*}}) + + // x86_64-windows: declare void @f( + // x86_64-windows-NOT: byval + // x86_64-windows-SAME: align 16{{.*}}) fn f(foo: Foo); } pub fn main() { - unsafe { f(Foo { a: [1; 16] }) } + unsafe { f(Foo { a: [1; 16], b: 2 }) } } -- cgit 1.4.1-3-g733a5 From be1d4e3e0b97ac07d6a76356a8714c0eaa39610b Mon Sep 17 00:00:00 2001 From: Erik Desjardins Date: Sat, 13 May 2023 22:00:37 -0400 Subject: update array-map test for removed alloca --- tests/codegen/array-map.rs | 1 - 1 file changed, 1 deletion(-) (limited to 'tests/codegen') diff --git a/tests/codegen/array-map.rs b/tests/codegen/array-map.rs index 24f3f43d078..4d218e6a951 100644 --- a/tests/codegen/array-map.rs +++ b/tests/codegen/array-map.rs @@ -30,7 +30,6 @@ pub fn short_integer_map(x: [u32; 8]) -> [u32; 8] { pub fn long_integer_map(x: [u32; 512]) -> [u32; 512] { // CHECK: start: // CHECK-NEXT: alloca [512 x i32] - // CHECK-NEXT: alloca %"core::mem::manually_drop::ManuallyDrop<[u32; 512]>" // CHECK-NOT: alloca // CHECK: mul <{{[0-9]+}} x i32> // CHECK: add <{{[0-9]+}} x i32> -- cgit 1.4.1-3-g733a5 From a07eb0abbd24e21716d476d7c363270c907f5d2e Mon Sep 17 00:00:00 2001 From: Erik Desjardins Date: Mon, 15 May 2023 00:49:12 -0400 Subject: implement vector-containing aggregate alignment for x86 darwin --- compiler/rustc_target/src/abi/call/x86.rs | 82 +++++++++++++++++++------------ tests/codegen/align-byval-vector.rs | 58 ++++++++++++++++++++++ 2 files changed, 109 insertions(+), 31 deletions(-) create mode 100644 tests/codegen/align-byval-vector.rs (limited to 'tests/codegen') diff --git a/compiler/rustc_target/src/abi/call/x86.rs b/compiler/rustc_target/src/abi/call/x86.rs index 58c0717b7d1..d2c604fafa6 100644 --- a/compiler/rustc_target/src/abi/call/x86.rs +++ b/compiler/rustc_target/src/abi/call/x86.rs @@ -1,5 +1,5 @@ use crate::abi::call::{ArgAttribute, FnAbi, PassMode, Reg, RegKind}; -use crate::abi::{Align, HasDataLayout, TyAbiInterface}; +use crate::abi::{Abi, Align, HasDataLayout, TyAbiInterface, TyAndLayout}; use crate::spec::HasTargetSpec; #[derive(PartialEq)] @@ -53,38 +53,58 @@ where if arg.is_ignore() { continue; } - if !arg.layout.is_aggregate() { - arg.extend_integer_width_to(32); - continue; - } - // We need to compute the alignment of the `byval` argument. The rules can be found in - // `X86_32ABIInfo::getTypeStackAlignInBytes` in Clang's `TargetInfo.cpp`. Summarized here, - // they are: - // - // 1. If the natural alignment of the type is less than or equal to 4, the alignment is 4. - // - // 2. Otherwise, on Linux, the alignment of any vector type is the natural alignment. - // (This doesn't matter here because we ensure we have an aggregate with the check above.) - // - // 3. Otherwise, on Apple platforms, the alignment of anything that contains a vector type - // is 16. - // - // 4. If none of these conditions are true, the alignment is 4. - let t = cx.target_spec(); - let align_4 = Align::from_bytes(4).unwrap(); - let align_16 = Align::from_bytes(16).unwrap(); - let byval_align = if arg.layout.align.abi < align_4 { - align_4 - } else if t.is_like_osx && arg.layout.align.abi >= align_16 { - // FIXME(pcwalton): This is dubious--we should actually be looking inside the type to - // determine if it contains SIMD vector values--but I think it's fine? - align_16 - } else { - align_4 - }; + if arg.layout.is_aggregate() { + // We need to compute the alignment of the `byval` argument. The rules can be found in + // `X86_32ABIInfo::getTypeStackAlignInBytes` in Clang's `TargetInfo.cpp`. Summarized + // here, they are: + // + // 1. If the natural alignment of the type is <= 4, the alignment is 4. + // + // 2. Otherwise, on Linux, the alignment of any vector type is the natural alignment. + // This doesn't matter here because we only pass aggregates via `byval`, not vectors. + // + // 3. Otherwise, on Apple platforms, the alignment of anything that contains a vector + // type is 16. + // + // 4. If none of these conditions are true, the alignment is 4. + + fn contains_vector<'a, Ty, C>(cx: &C, layout: TyAndLayout<'a, Ty>) -> bool + where + Ty: TyAbiInterface<'a, C> + Copy, + { + match layout.abi { + Abi::Uninhabited | Abi::Scalar(_) | Abi::ScalarPair(..) => false, + Abi::Vector { .. } => true, + Abi::Aggregate { .. } => { + for i in 0..layout.fields.count() { + if contains_vector(cx, layout.field(cx, i)) { + return true; + } + } + false + } + } + } - arg.make_indirect_byval(Some(byval_align)); + let t = cx.target_spec(); + let align_4 = Align::from_bytes(4).unwrap(); + let align_16 = Align::from_bytes(16).unwrap(); + let byval_align = if arg.layout.align.abi < align_4 { + // (1.) + align_4 + } else if t.is_like_osx && contains_vector(cx, arg.layout) { + // (3.) + align_16 + } else { + // (4.) + align_4 + }; + + arg.make_indirect_byval(Some(byval_align)); + } else { + arg.extend_integer_width_to(32); + } } if flavor == Flavor::FastcallOrVectorcall { diff --git a/tests/codegen/align-byval-vector.rs b/tests/codegen/align-byval-vector.rs new file mode 100644 index 00000000000..3c8be659671 --- /dev/null +++ b/tests/codegen/align-byval-vector.rs @@ -0,0 +1,58 @@ +// revisions:x86-linux x86-darwin + +//[x86-linux] compile-flags: --target i686-unknown-linux-gnu +//[x86-linux] needs-llvm-components: x86 +//[x86-darwin] compile-flags: --target i686-apple-darwin +//[x86-darwin] needs-llvm-components: x86 + +// Tests that aggregates containing vector types get their alignment increased to 16 on Darwin. + +#![feature(no_core, lang_items, repr_simd, simd_ffi)] +#![crate_type = "lib"] +#![no_std] +#![no_core] +#![allow(non_camel_case_types)] + +#[lang = "sized"] +trait Sized {} +#[lang = "freeze"] +trait Freeze {} +#[lang = "copy"] +trait Copy {} + +#[repr(simd)] +pub struct i32x4(i32, i32, i32, i32); + +#[repr(C)] +pub struct Foo { + a: i32x4, + b: i8, +} + +// This tests that we recursively check for vector types, not just at the top level. +#[repr(C)] +pub struct DoubleFoo { + one: Foo, + two: Foo, +} + +extern "C" { + // x86-linux: declare void @f({{.*}}byval(%Foo) align 4{{.*}}) + // x86-darwin: declare void @f({{.*}}byval(%Foo) align 16{{.*}}) + fn f(foo: Foo); + + // x86-linux: declare void @g({{.*}}byval(%DoubleFoo) align 4{{.*}}) + // x86-darwin: declare void @g({{.*}}byval(%DoubleFoo) align 16{{.*}}) + fn g(foo: DoubleFoo); +} + +pub fn main() { + unsafe { f(Foo { a: i32x4(1, 2, 3, 4), b: 0 }) } + + unsafe { + g(DoubleFoo { + one: Foo { a: i32x4(1, 2, 3, 4), b: 0 }, + two: Foo { a: i32x4(1, 2, 3, 4), b: 0 }, + }) + } +} -- cgit 1.4.1-3-g733a5 From fdaaf86cc03421dc96d755bc9e6c5984b124028d Mon Sep 17 00:00:00 2001 From: Erik Desjardins Date: Tue, 16 May 2023 20:25:15 -0400 Subject: add align attr to addr-of-mutate test --- tests/codegen/addr-of-mutate.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'tests/codegen') diff --git a/tests/codegen/addr-of-mutate.rs b/tests/codegen/addr-of-mutate.rs index bea1aad2352..6dfc1825015 100644 --- a/tests/codegen/addr-of-mutate.rs +++ b/tests/codegen/addr-of-mutate.rs @@ -6,7 +6,7 @@ // Test for the absence of `readonly` on the argument when it is mutated via `&raw const`. // See . -// CHECK: i8 @foo(ptr noalias nocapture noundef dereferenceable(128) %x) +// CHECK: i8 @foo(ptr noalias nocapture noundef align 1 dereferenceable(128) %x) #[no_mangle] pub fn foo(x: [u8; 128]) -> u8 { let ptr = core::ptr::addr_of!(x).cast_mut(); @@ -16,7 +16,7 @@ pub fn foo(x: [u8; 128]) -> u8 { x[0] } -// CHECK: i1 @second(ptr noalias nocapture noundef dereferenceable({{[0-9]+}}) %a_ptr_and_b) +// CHECK: i1 @second(ptr noalias nocapture noundef align {{[0-9]+}} dereferenceable({{[0-9]+}}) %a_ptr_and_b) #[no_mangle] pub unsafe fn second(a_ptr_and_b: (*mut (i32, bool), (i64, bool))) -> bool { let b_bool_ptr = core::ptr::addr_of!(a_ptr_and_b.1.1).cast_mut(); @@ -25,7 +25,7 @@ pub unsafe fn second(a_ptr_and_b: (*mut (i32, bool), (i64, bool))) -> bool { } // If going through a deref (and there are no other mutating accesses), then `readonly` is fine. -// CHECK: i1 @third(ptr noalias nocapture noundef readonly dereferenceable({{[0-9]+}}) %a_ptr_and_b) +// CHECK: i1 @third(ptr noalias nocapture noundef readonly align {{[0-9]+}} dereferenceable({{[0-9]+}}) %a_ptr_and_b) #[no_mangle] pub unsafe fn third(a_ptr_and_b: (*mut (i32, bool), (i64, bool))) -> bool { let b_bool_ptr = core::ptr::addr_of!((*a_ptr_and_b.0).1).cast_mut(); -- cgit 1.4.1-3-g733a5 From 08d18929fbd343cd46e8a8216c0c8d67f9763216 Mon Sep 17 00:00:00 2001 From: Erik Desjardins Date: Sat, 20 May 2023 01:30:59 -0400 Subject: align-byval test: add x86 x86 Windows also should not use byval since the struct is overaligned, see https://reviews.llvm.org/D72114 --- tests/codegen/align-byval.rs | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) (limited to 'tests/codegen') diff --git a/tests/codegen/align-byval.rs b/tests/codegen/align-byval.rs index 4315c3371e1..1470e7bf782 100644 --- a/tests/codegen/align-byval.rs +++ b/tests/codegen/align-byval.rs @@ -1,4 +1,4 @@ -// revisions:m68k wasm x86_64-linux x86_64-windows +// revisions:m68k wasm x86_64-linux x86_64-windows i686-linux i686-windows //[m68k] compile-flags: --target m68k-unknown-linux-gnu //[m68k] needs-llvm-components: m68k @@ -8,10 +8,13 @@ //[x86_64-linux] needs-llvm-components: x86 //[x86_64-windows] compile-flags: --target x86_64-pc-windows-msvc //[x86_64-windows] needs-llvm-components: x86 +//[i686-linux] compile-flags: --target i686-unknown-linux-gnu +//[i686-linux] needs-llvm-components: x86 +//[i686-windows] compile-flags: --target i686-pc-windows-msvc +//[i686-windows] needs-llvm-components: x86 // Tests that `byval` alignment is properly specified (#80127). -// The only targets that use `byval` are m68k, wasm, x86-64, and x86. Note that -// x86 has special rules (see #103830), and it's therefore ignored here. +// The only targets that use `byval` are m68k, wasm, x86-64, and x86. // Note also that Windows mandates a by-ref ABI here, so it does not use byval. #![feature(no_core, lang_items)] @@ -43,6 +46,12 @@ extern "C" { // x86_64-windows: declare void @f( // x86_64-windows-NOT: byval // x86_64-windows-SAME: align 16{{.*}}) + + // i686-linux: declare void @f({{.*}}byval(%Foo) align 4{{.*}}) + + // i686-windows: declare void @f( + // i686-windows-NOT: byval + // i686-windows-SAME: align 16{{.*}}) fn f(foo: Foo); } -- cgit 1.4.1-3-g733a5 From 8ec90f6f14a5c2c8cc454e78f87b7fc6347fe2f8 Mon Sep 17 00:00:00 2001 From: Erik Desjardins Date: Sat, 20 May 2023 15:32:37 -0400 Subject: align-byval test: add cases distinguishing natural vs forced/requested alignment --- tests/codegen/align-byval.rs | 72 ++++++++++++++++++++++++++++++++++++++------ 1 file changed, 62 insertions(+), 10 deletions(-) (limited to 'tests/codegen') diff --git a/tests/codegen/align-byval.rs b/tests/codegen/align-byval.rs index 1470e7bf782..10ded42bd66 100644 --- a/tests/codegen/align-byval.rs +++ b/tests/codegen/align-byval.rs @@ -29,32 +29,84 @@ impl Copy for i32 {} impl Copy for i64 {} +// on i686-windows, this should be passed on stack using `byval` +#[repr(C)] +pub struct NaturalAlign8 { + a: i64, + b: i64, + c: i64 +} + +// on i686-windows, this should be passed by reference (because the alignment is requested/forced), +// even though it has the exact same layout as `NaturalAlign8` (!!!) +#[repr(C)] +#[repr(align(8))] +pub struct ForceAlign8 { + a: i64, + b: i64, + c: i64 +} + #[repr(C)] #[repr(align(16))] -struct Foo { +pub struct ForceAlign16 { a: [i32; 16], b: i8 } extern "C" { - // m68k: declare void @f({{.*}}byval(%Foo) align 16{{.*}}) + // m68k: declare void @natural_align_8({{.*}}byval(%NaturalAlign8) align 4{{.*}}) + + // wasm: declare void @natural_align_8({{.*}}byval(%NaturalAlign8) align 8{{.*}}) + + // x86_64-linux: declare void @natural_align_8({{.*}}byval(%NaturalAlign8) align 8{{.*}}) + + // x86_64-windows: declare void @natural_align_8( + // x86_64-windows-NOT: byval + // x86_64-windows-SAME: align 8{{.*}}) + + // i686-linux: declare void @natural_align_8({{.*}}byval(%NaturalAlign8) align 4{{.*}}) + + // i686-windows: declare void @natural_align_8({{.*}}byval(%NaturalAlign8) align 4{{.*}}) + fn natural_align_8(x: NaturalAlign8); + + // m68k: declare void @force_align_8({{.*}}byval(%ForceAlign8) align 8{{.*}}) + + // wasm: declare void @force_align_8({{.*}}byval(%ForceAlign8) align 8{{.*}}) + + // x86_64-linux: declare void @force_align_8({{.*}}byval(%ForceAlign8) align 8{{.*}}) + + // x86_64-windows: declare void @force_align_8( + // x86_64-windows-NOT: byval + // x86_64-windows-SAME: align 8{{.*}}) + + // i686-linux: declare void @force_align_8({{.*}}byval(%ForceAlign8) align 4{{.*}}) + + // i686-windows: declare void @force_align_8( + // i686-windows-NOT: byval + // i686-windows-SAME: align 8{{.*}}) + fn force_align_8(y: ForceAlign8); + + // m68k: declare void @force_align_16({{.*}}byval(%ForceAlign16) align 16{{.*}}) - // wasm: declare void @f({{.*}}byval(%Foo) align 16{{.*}}) + // wasm: declare void @force_align_16({{.*}}byval(%ForceAlign16) align 16{{.*}}) - // x86_64-linux: declare void @f({{.*}}byval(%Foo) align 16{{.*}}) + // x86_64-linux: declare void @force_align_16({{.*}}byval(%ForceAlign16) align 16{{.*}}) - // x86_64-windows: declare void @f( + // x86_64-windows: declare void @force_align_16( // x86_64-windows-NOT: byval // x86_64-windows-SAME: align 16{{.*}}) - // i686-linux: declare void @f({{.*}}byval(%Foo) align 4{{.*}}) + // i686-linux: declare void @force_align_16({{.*}}byval(%ForceAlign16) align 4{{.*}}) - // i686-windows: declare void @f( + // i686-windows: declare void @force_align_16( // i686-windows-NOT: byval // i686-windows-SAME: align 16{{.*}}) - fn f(foo: Foo); + fn force_align_16(z: ForceAlign16); } -pub fn main() { - unsafe { f(Foo { a: [1; 16], b: 2 }) } +pub unsafe fn main(x: NaturalAlign8, y: ForceAlign8, z: ForceAlign16) { + natural_align_8(x); + force_align_8(y); + force_align_16(z); } -- cgit 1.4.1-3-g733a5 From 209ed071bab1cad917c825c55f3a83feb72cd664 Mon Sep 17 00:00:00 2001 From: Erik Desjardins Date: Sat, 20 May 2023 16:54:12 -0400 Subject: align-byval test: add cases for <= align 4 --- tests/codegen/align-byval.rs | 52 ++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 50 insertions(+), 2 deletions(-) (limited to 'tests/codegen') diff --git a/tests/codegen/align-byval.rs b/tests/codegen/align-byval.rs index 10ded42bd66..03641b00c5f 100644 --- a/tests/codegen/align-byval.rs +++ b/tests/codegen/align-byval.rs @@ -29,6 +29,19 @@ impl Copy for i32 {} impl Copy for i64 {} +#[repr(C)] +pub struct NaturalAlign2 { + a: [i16; 16], + b: i16, +} + +#[repr(C)] +#[repr(align(4))] +pub struct ForceAlign4 { + a: [i8; 16], + b: i8, +} + // on i686-windows, this should be passed on stack using `byval` #[repr(C)] pub struct NaturalAlign8 { @@ -37,7 +50,7 @@ pub struct NaturalAlign8 { c: i64 } -// on i686-windows, this should be passed by reference (because the alignment is requested/forced), +// on i686-windows, this is passed by reference (because alignment is >4 and requested/forced), // even though it has the exact same layout as `NaturalAlign8` (!!!) #[repr(C)] #[repr(align(8))] @@ -55,6 +68,36 @@ pub struct ForceAlign16 { } extern "C" { + // m68k: declare void @natural_align_2({{.*}}byval(%NaturalAlign2) align 2{{.*}}) + + // wasm: declare void @natural_align_2({{.*}}byval(%NaturalAlign2) align 2{{.*}}) + + // x86_64-linux: declare void @natural_align_2({{.*}}byval(%NaturalAlign2) align 2{{.*}}) + + // x86_64-windows: declare void @natural_align_2( + // x86_64-windows-NOT: byval + // x86_64-windows-SAME: align 2{{.*}}) + + // i686-linux: declare void @natural_align_2({{.*}}byval(%NaturalAlign2) align 4{{.*}}) + + // i686-windows: declare void @natural_align_2({{.*}}byval(%NaturalAlign2) align 4{{.*}}) + fn natural_align_2(a: NaturalAlign2); + + // m68k: declare void @force_align_4({{.*}}byval(%ForceAlign4) align 4{{.*}}) + + // wasm: declare void @force_align_4({{.*}}byval(%ForceAlign4) align 4{{.*}}) + + // x86_64-linux: declare void @force_align_4({{.*}}byval(%ForceAlign4) align 4{{.*}}) + + // x86_64-windows: declare void @force_align_4( + // x86_64-windows-NOT: byval + // x86_64-windows-SAME: align 4{{.*}}) + + // i686-linux: declare void @force_align_4({{.*}}byval(%ForceAlign4) align 4{{.*}}) + + // i686-windows: declare void @force_align_4({{.*}}byval(%ForceAlign4) align 4{{.*}}) + fn force_align_4(b: ForceAlign4); + // m68k: declare void @natural_align_8({{.*}}byval(%NaturalAlign8) align 4{{.*}}) // wasm: declare void @natural_align_8({{.*}}byval(%NaturalAlign8) align 8{{.*}}) @@ -105,7 +148,12 @@ extern "C" { fn force_align_16(z: ForceAlign16); } -pub unsafe fn main(x: NaturalAlign8, y: ForceAlign8, z: ForceAlign16) { +pub unsafe fn main( + a: NaturalAlign2, b: ForceAlign4, + x: NaturalAlign8, y: ForceAlign8, z: ForceAlign16 +) { + natural_align_2(a); + force_align_4(b); natural_align_8(x); force_align_8(y); force_align_16(z); -- cgit 1.4.1-3-g733a5 From 0e76446a9ff834b402c352b495cc1bb30c30d3cb Mon Sep 17 00:00:00 2001 From: Erik Desjardins Date: Sat, 10 Jun 2023 22:16:11 -0400 Subject: ensure byval allocas are sufficiently aligned --- compiler/rustc_codegen_ssa/src/mir/block.rs | 68 ++++++++++------ compiler/rustc_codegen_ssa/src/mir/place.rs | 12 ++- tests/codegen/align-byval.rs | 116 ++++++++++++++++++++++++---- 3 files changed, 157 insertions(+), 39 deletions(-) (limited to 'tests/codegen') diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs index 9d1b3ce8266..07e21225a6f 100644 --- a/compiler/rustc_codegen_ssa/src/mir/block.rs +++ b/compiler/rustc_codegen_ssa/src/mir/block.rs @@ -23,6 +23,8 @@ use rustc_target::abi::call::{ArgAbi, FnAbi, PassMode, Reg}; use rustc_target::abi::{self, HasDataLayout, WrappingRange}; use rustc_target::spec::abi::Abi; +use std::cmp; + // Indicates if we are in the middle of merging a BB's successor into it. This // can happen when BB jumps directly to its successor and the successor has no // other predecessors. @@ -1360,36 +1362,58 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { // Force by-ref if we have to load through a cast pointer. let (mut llval, align, by_ref) = match op.val { Immediate(_) | Pair(..) => match arg.mode { - PassMode::Indirect { .. } | PassMode::Cast(..) => { + PassMode::Indirect { attrs, .. } => { + // Indirect argument may have higher alignment requirements than the type's alignment. + // This can happen, e.g. when passing types with <4 byte alignment on the stack on x86. + let required_align = match attrs.pointee_align { + Some(pointee_align) => cmp::max(pointee_align, arg.layout.align.abi), + None => arg.layout.align.abi, + }; + let scratch = PlaceRef::alloca_aligned(bx, arg.layout, required_align); + op.val.store(bx, scratch); + (scratch.llval, scratch.align, true) + } + PassMode::Cast(..) => { let scratch = PlaceRef::alloca(bx, arg.layout); op.val.store(bx, scratch); (scratch.llval, scratch.align, true) } _ => (op.immediate_or_packed_pair(bx), arg.layout.align.abi, false), }, - Ref(llval, _, align) => { - if arg.is_indirect() && align < arg.layout.align.abi { - // `foo(packed.large_field)`. We can't pass the (unaligned) field directly. I - // think that ATM (Rust 1.16) we only pass temporaries, but we shouldn't - // have scary latent bugs around. - - let scratch = PlaceRef::alloca(bx, arg.layout); - base::memcpy_ty( - bx, - scratch.llval, - scratch.align, - llval, - align, - op.layout, - MemFlags::empty(), - ); - (scratch.llval, scratch.align, true) - } else { - (llval, align, true) + Ref(llval, _, align) => match arg.mode { + PassMode::Indirect { attrs, .. } => { + let required_align = match attrs.pointee_align { + Some(pointee_align) => cmp::max(pointee_align, arg.layout.align.abi), + None => arg.layout.align.abi, + }; + if align < required_align { + // For `foo(packed.large_field)`, and types with <4 byte alignment on x86, + // alignment requirements may be higher than the type's alignment, so copy + // to a higher-aligned alloca. + let scratch = PlaceRef::alloca_aligned(bx, arg.layout, required_align); + base::memcpy_ty( + bx, + scratch.llval, + scratch.align, + llval, + align, + op.layout, + MemFlags::empty(), + ); + (scratch.llval, scratch.align, true) + } else { + (llval, align, true) + } } - } + _ => (llval, align, true), + }, ZeroSized => match arg.mode { - PassMode::Indirect { .. } => { + PassMode::Indirect { on_stack, .. } => { + if on_stack { + // It doesn't seem like any target can have `byval` ZSTs, so this assert + // is here to replace a would-be untested codepath. + bug!("ZST {op:?} passed on stack with abi {arg:?}"); + } // Though `extern "Rust"` doesn't pass ZSTs, some ABIs pass // a pointer for `repr(C)` structs even when empty, so get // one from an `alloca` (which can be left uninitialized). diff --git a/compiler/rustc_codegen_ssa/src/mir/place.rs b/compiler/rustc_codegen_ssa/src/mir/place.rs index ab493ae5c1f..90eab55f76e 100644 --- a/compiler/rustc_codegen_ssa/src/mir/place.rs +++ b/compiler/rustc_codegen_ssa/src/mir/place.rs @@ -47,10 +47,18 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> { pub fn alloca>( bx: &mut Bx, layout: TyAndLayout<'tcx>, + ) -> Self { + Self::alloca_aligned(bx, layout, layout.align.abi) + } + + pub fn alloca_aligned>( + bx: &mut Bx, + layout: TyAndLayout<'tcx>, + align: Align, ) -> Self { assert!(layout.is_sized(), "tried to statically allocate unsized place"); - let tmp = bx.alloca(bx.cx().backend_type(layout), layout.align.abi); - Self::new_sized(tmp, layout) + let tmp = bx.alloca(bx.cx().backend_type(layout), align); + Self::new_sized_aligned(tmp, layout, align) } /// Returns a place for an indirect reference to an unsized place. diff --git a/tests/codegen/align-byval.rs b/tests/codegen/align-byval.rs index 03641b00c5f..6a9f7fae6a8 100644 --- a/tests/codegen/align-byval.rs +++ b/tests/codegen/align-byval.rs @@ -1,3 +1,4 @@ +// ignore-tidy-linelength // revisions:m68k wasm x86_64-linux x86_64-windows i686-linux i686-windows //[m68k] compile-flags: --target m68k-unknown-linux-gnu @@ -29,6 +30,16 @@ impl Copy for i32 {} impl Copy for i64 {} +// This struct can be represented as a pair, so it exercises the OperandValue::Pair +// codepath in `codegen_argument`. +#[repr(C)] +pub struct NaturalAlign1 { + a: i8, + b: i8, +} + +// This struct cannot be represented as an immediate, so it exercises the OperandValue::Ref +// codepath in `codegen_argument`. #[repr(C)] pub struct NaturalAlign2 { a: [i16; 16], @@ -67,7 +78,93 @@ pub struct ForceAlign16 { b: i8 } +// CHECK-LABEL: @call_na1 +#[no_mangle] +pub unsafe fn call_na1(x: NaturalAlign1) { + // CHECK: start: + + // m68k: [[ALLOCA:%[a-z0-9+]]] = alloca { i8, i8 }, align 1 + // m68k: call void @natural_align_1({{.*}}byval({ i8, i8 }) align 1{{.*}} [[ALLOCA]]) + + // wasm: [[ALLOCA:%[a-z0-9+]]] = alloca { i8, i8 }, align 1 + // wasm: call void @natural_align_1({{.*}}byval({ i8, i8 }) align 1{{.*}} [[ALLOCA]]) + + // x86_64-linux: call void @natural_align_1(i16 + + // x86_64-windows: call void @natural_align_1(i16 + + // i686-linux: [[ALLOCA:%[a-z0-9+]]] = alloca { i8, i8 }, align 4 + // i686-linux: call void @natural_align_1({{.*}}byval({ i8, i8 }) align 4{{.*}} [[ALLOCA]]) + + // i686-windows: [[ALLOCA:%[a-z0-9+]]] = alloca { i8, i8 }, align 4 + // i686-windows: call void @natural_align_1({{.*}}byval({ i8, i8 }) align 4{{.*}} [[ALLOCA]]) + natural_align_1(x); +} + +// CHECK-LABEL: @call_na2 +#[no_mangle] +pub unsafe fn call_na2(x: NaturalAlign2) { + // CHECK: start: + + // m68k-NEXT: call void @natural_align_2 + // wasm-NEXT: call void @natural_align_2 + // x86_64-linux-NEXT: call void @natural_align_2 + // x86_64-windows-NEXT: call void @natural_align_2 + + // i686-linux: [[ALLOCA:%[0-9]+]] = alloca %NaturalAlign2, align 4 + // i686-linux: call void @natural_align_2({{.*}}byval(%NaturalAlign2) align 4{{.*}} [[ALLOCA]]) + + // i686-windows: [[ALLOCA:%[0-9]+]] = alloca %NaturalAlign2, align 4 + // i686-windows: call void @natural_align_2({{.*}}byval(%NaturalAlign2) align 4{{.*}} [[ALLOCA]]) + natural_align_2(x); +} + +// CHECK-LABEL: @call_fa4 +#[no_mangle] +pub unsafe fn call_fa4(x: ForceAlign4) { + // CHECK: start: + // CHECK-NEXT: call void @force_align_4 + force_align_4(x); +} + +// CHECK-LABEL: @call_na8 +#[no_mangle] +pub unsafe fn call_na8(x: NaturalAlign8) { + // CHECK: start: + // CHECK-NEXT: call void @natural_align_8 + natural_align_8(x); +} + +// CHECK-LABEL: @call_fa8 +#[no_mangle] +pub unsafe fn call_fa8(x: ForceAlign8) { + // CHECK: start: + // CHECK-NEXT: call void @force_align_8 + force_align_8(x); +} + +// CHECK-LABEL: @call_fa16 +#[no_mangle] +pub unsafe fn call_fa16(x: ForceAlign16) { + // CHECK: start: + // CHECK-NEXT: call void @force_align_16 + force_align_16(x); +} + extern "C" { + // m68k: declare void @natural_align_1({{.*}}byval({ i8, i8 }) align 1{{.*}}) + + // wasm: declare void @natural_align_1({{.*}}byval({ i8, i8 }) align 1{{.*}}) + + // x86_64-linux: declare void @natural_align_1(i16) + + // x86_64-windows: declare void @natural_align_1(i16) + + // i686-linux: declare void @natural_align_1({{.*}}byval({ i8, i8 }) align 4{{.*}}) + + // i686-windows: declare void @natural_align_1({{.*}}byval({ i8, i8 }) align 4{{.*}}) + fn natural_align_1(x: NaturalAlign1); + // m68k: declare void @natural_align_2({{.*}}byval(%NaturalAlign2) align 2{{.*}}) // wasm: declare void @natural_align_2({{.*}}byval(%NaturalAlign2) align 2{{.*}}) @@ -81,7 +178,7 @@ extern "C" { // i686-linux: declare void @natural_align_2({{.*}}byval(%NaturalAlign2) align 4{{.*}}) // i686-windows: declare void @natural_align_2({{.*}}byval(%NaturalAlign2) align 4{{.*}}) - fn natural_align_2(a: NaturalAlign2); + fn natural_align_2(x: NaturalAlign2); // m68k: declare void @force_align_4({{.*}}byval(%ForceAlign4) align 4{{.*}}) @@ -96,7 +193,7 @@ extern "C" { // i686-linux: declare void @force_align_4({{.*}}byval(%ForceAlign4) align 4{{.*}}) // i686-windows: declare void @force_align_4({{.*}}byval(%ForceAlign4) align 4{{.*}}) - fn force_align_4(b: ForceAlign4); + fn force_align_4(x: ForceAlign4); // m68k: declare void @natural_align_8({{.*}}byval(%NaturalAlign8) align 4{{.*}}) @@ -128,7 +225,7 @@ extern "C" { // i686-windows: declare void @force_align_8( // i686-windows-NOT: byval // i686-windows-SAME: align 8{{.*}}) - fn force_align_8(y: ForceAlign8); + fn force_align_8(x: ForceAlign8); // m68k: declare void @force_align_16({{.*}}byval(%ForceAlign16) align 16{{.*}}) @@ -145,16 +242,5 @@ extern "C" { // i686-windows: declare void @force_align_16( // i686-windows-NOT: byval // i686-windows-SAME: align 16{{.*}}) - fn force_align_16(z: ForceAlign16); -} - -pub unsafe fn main( - a: NaturalAlign2, b: ForceAlign4, - x: NaturalAlign8, y: ForceAlign8, z: ForceAlign16 -) { - natural_align_2(a); - force_align_4(b); - natural_align_8(x); - force_align_8(y); - force_align_16(z); + fn force_align_16(x: ForceAlign16); } -- cgit 1.4.1-3-g733a5 From f704396c0e26fd6de1cfb4e03e1749e9829a11ea Mon Sep 17 00:00:00 2001 From: Erik Desjardins Date: Sun, 11 Jun 2023 13:40:47 -0400 Subject: align-byval test: add cases for lower requested alignment, wrapped, and repr(transparent) --- tests/codegen/align-byval.rs | 103 +++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 100 insertions(+), 3 deletions(-) (limited to 'tests/codegen') diff --git a/tests/codegen/align-byval.rs b/tests/codegen/align-byval.rs index 6a9f7fae6a8..2c64230bfd0 100644 --- a/tests/codegen/align-byval.rs +++ b/tests/codegen/align-byval.rs @@ -53,7 +53,7 @@ pub struct ForceAlign4 { b: i8, } -// on i686-windows, this should be passed on stack using `byval` +// On i686-windows, this is passed on stack using `byval` #[repr(C)] pub struct NaturalAlign8 { a: i64, @@ -61,8 +61,8 @@ pub struct NaturalAlign8 { c: i64 } -// on i686-windows, this is passed by reference (because alignment is >4 and requested/forced), -// even though it has the exact same layout as `NaturalAlign8` (!!!) +// On i686-windows, this is passed by reference (because alignment is >4 and requested/forced), +// even though it has the exact same layout as `NaturalAlign8`! #[repr(C)] #[repr(align(8))] pub struct ForceAlign8 { @@ -71,6 +71,30 @@ pub struct ForceAlign8 { c: i64 } +// On i686-windows, this is passed by reference because alignment is requested, +// even though the requested alignment is less than the natural alignment. +#[repr(C)] +#[repr(align(1))] +pub struct LowerFA8 { + a: i64, + b: i64, + c: i64 +} + +// On i686-windows, this is passed on stack again, because the wrapper struct does not have +// requested/forced alignment. +#[repr(C)] +pub struct WrappedFA8 { + a: ForceAlign8 +} + +// On i686-windows, this has the same ABI as ForceAlign8, i.e. passed by reference. +#[repr(transparent)] +pub struct TransparentFA8 { + _0: (), + a: ForceAlign8 +} + #[repr(C)] #[repr(align(16))] pub struct ForceAlign16 { @@ -143,6 +167,30 @@ pub unsafe fn call_fa8(x: ForceAlign8) { force_align_8(x); } +// CHECK-LABEL: @call_lfa8 +#[no_mangle] +pub unsafe fn call_lfa8(x: LowerFA8) { + // CHECK: start: + // CHECK-NEXT: call void @lower_fa8 + lower_fa8(x); +} + +// CHECK-LABEL: @call_wfa8 +#[no_mangle] +pub unsafe fn call_wfa8(x: WrappedFA8) { + // CHECK: start: + // CHECK-NEXT: call void @wrapped_fa8 + wrapped_fa8(x); +} + +// CHECK-LABEL: @call_tfa8 +#[no_mangle] +pub unsafe fn call_tfa8(x: TransparentFA8) { + // CHECK: start: + // CHECK-NEXT: call void @transparent_fa8 + transparent_fa8(x); +} + // CHECK-LABEL: @call_fa16 #[no_mangle] pub unsafe fn call_fa16(x: ForceAlign16) { @@ -227,6 +275,55 @@ extern "C" { // i686-windows-SAME: align 8{{.*}}) fn force_align_8(x: ForceAlign8); + // m68k: declare void @lower_fa8({{.*}}byval(%LowerFA8) align 4{{.*}}) + + // wasm: declare void @lower_fa8({{.*}}byval(%LowerFA8) align 8{{.*}}) + + // x86_64-linux: declare void @lower_fa8({{.*}}byval(%LowerFA8) align 8{{.*}}) + + // x86_64-windows: declare void @lower_fa8( + // x86_64-windows-NOT: byval + // x86_64-windows-SAME: align 8{{.*}}) + + // i686-linux: declare void @lower_fa8({{.*}}byval(%LowerFA8) align 4{{.*}}) + + // i686-windows: declare void @lower_fa8( + // i686-windows-NOT: byval + // i686-windows-SAME: align 8{{.*}}) + fn lower_fa8(x: LowerFA8); + + // m68k: declare void @wrapped_fa8({{.*}}byval(%WrappedFA8) align 8{{.*}}) + + // wasm: declare void @wrapped_fa8({{.*}}byval(%WrappedFA8) align 8{{.*}}) + + // x86_64-linux: declare void @wrapped_fa8({{.*}}byval(%WrappedFA8) align 8{{.*}}) + + // x86_64-windows: declare void @wrapped_fa8( + // x86_64-windows-NOT: byval + // x86_64-windows-SAME: align 8{{.*}}) + + // i686-linux: declare void @wrapped_fa8({{.*}}byval(%WrappedFA8) align 4{{.*}}) + + // i686-windows: declare void @wrapped_fa8({{.*}}byval(%WrappedFA8) align 4{{.*}}) + fn wrapped_fa8(x: WrappedFA8); + + // m68k: declare void @transparent_fa8({{.*}}byval(%TransparentFA8) align 8{{.*}}) + + // wasm: declare void @transparent_fa8({{.*}}byval(%TransparentFA8) align 8{{.*}}) + + // x86_64-linux: declare void @transparent_fa8({{.*}}byval(%TransparentFA8) align 8{{.*}}) + + // x86_64-windows: declare void @transparent_fa8( + // x86_64-windows-NOT: byval + // x86_64-windows-SAME: align 8{{.*}}) + + // i686-linux: declare void @transparent_fa8({{.*}}byval(%TransparentFA8) align 4{{.*}}) + + // i686-windows: declare void @transparent_fa8( + // i686-windows-NOT: byval + // i686-windows-SAME: align 8{{.*}}) + fn transparent_fa8(x: TransparentFA8); + // m68k: declare void @force_align_16({{.*}}byval(%ForceAlign16) align 16{{.*}}) // wasm: declare void @force_align_16({{.*}}byval(%ForceAlign16) align 16{{.*}}) -- cgit 1.4.1-3-g733a5 From 7e933b4e26947b04da70589110dacbdb2461e27d Mon Sep 17 00:00:00 2001 From: Erik Desjardins Date: Sun, 11 Jun 2023 17:05:26 -0400 Subject: repr(align) <= 4 should still be byval --- compiler/rustc_abi/src/layout.rs | 18 +++++------ compiler/rustc_abi/src/lib.rs | 16 +++++----- .../rustc_codegen_cranelift/src/abi/comments.rs | 2 +- compiler/rustc_middle/src/ty/layout.rs | 2 +- compiler/rustc_target/src/abi/call/x86.rs | 8 +++-- compiler/rustc_ty_utils/src/layout.rs | 10 +++--- tests/codegen/align-byval.rs | 11 +++---- tests/ui/layout/debug.stderr | 36 +++++++++++----------- tests/ui/layout/hexagon-enum.stderr | 20 ++++++------ ...96158-scalarpair-payload-might-be-uninit.stderr | 34 ++++++++++---------- .../ui/layout/issue-96185-overaligned-enum.stderr | 24 +++++++++++---- tests/ui/layout/thumb-enum.stderr | 20 ++++++------ tests/ui/layout/zero-sized-array-enum-niche.stderr | 26 ++++++++-------- 13 files changed, 120 insertions(+), 107 deletions(-) (limited to 'tests/codegen') diff --git a/compiler/rustc_abi/src/layout.rs b/compiler/rustc_abi/src/layout.rs index efae34e95df..ff811be3c81 100644 --- a/compiler/rustc_abi/src/layout.rs +++ b/compiler/rustc_abi/src/layout.rs @@ -40,7 +40,7 @@ pub trait LayoutCalculator { largest_niche, align, size, - has_repr_align: false, + repr_align: None, } } @@ -123,7 +123,7 @@ pub trait LayoutCalculator { largest_niche: None, align: dl.i8_align, size: Size::ZERO, - has_repr_align: false, + repr_align: None, } } @@ -424,7 +424,7 @@ pub trait LayoutCalculator { largest_niche, size, align, - has_repr_align: repr.align.is_some(), + repr_align: repr.align, }; Some(TmpLayout { layout, variants: variant_layouts }) @@ -694,7 +694,7 @@ pub trait LayoutCalculator { abi, align, size, - has_repr_align: repr.align.is_some(), + repr_align: repr.align, }; let tagged_layout = TmpLayout { layout: tagged_layout, variants: layout_variants }; @@ -813,7 +813,7 @@ pub trait LayoutCalculator { largest_niche: None, align, size: size.align_to(align.abi), - has_repr_align: repr.align.is_some(), + repr_align: repr.align, }) } } @@ -1111,9 +1111,9 @@ fn univariant( abi = Abi::Uninhabited; } - let has_repr_align = repr.align.is_some() - || repr.transparent() - && layout_of_single_non_zst_field.map_or(false, |l| l.has_repr_align()); + let repr_align = repr.align.or_else(|| { + if repr.transparent() { layout_of_single_non_zst_field?.repr_align() } else { None } + }); Some(LayoutS { variants: Variants::Single { index: FIRST_VARIANT }, @@ -1122,7 +1122,7 @@ fn univariant( largest_niche, align, size, - has_repr_align, + repr_align, }) } diff --git a/compiler/rustc_abi/src/lib.rs b/compiler/rustc_abi/src/lib.rs index 4cf6289ae00..b1577add4d0 100644 --- a/compiler/rustc_abi/src/lib.rs +++ b/compiler/rustc_abi/src/lib.rs @@ -1532,10 +1532,10 @@ pub struct LayoutS { pub align: AbiAndPrefAlign, pub size: Size, - /// True if the alignment was explicitly requested with `repr(align)`. + /// The alignment explicitly requested with `repr(align)`. /// Only used on i686-windows, where the argument passing ABI is different when alignment is - /// requested, even if the requested alignment is equal to or less than the natural alignment. - pub has_repr_align: bool, + /// requested, even if the requested alignment is equal to the natural alignment. + pub repr_align: Option, } impl LayoutS { @@ -1550,7 +1550,7 @@ impl LayoutS { largest_niche, size, align, - has_repr_align: false, + repr_align: None, } } } @@ -1560,7 +1560,7 @@ impl fmt::Debug for LayoutS { // This is how `Layout` used to print before it become // `Interned`. We print it like this to avoid having to update // expected output in a lot of tests. - let LayoutS { size, align, abi, fields, largest_niche, variants, has_repr_align } = self; + let LayoutS { size, align, abi, fields, largest_niche, variants, repr_align } = self; f.debug_struct("Layout") .field("size", size) .field("align", align) @@ -1568,7 +1568,7 @@ impl fmt::Debug for LayoutS { .field("fields", fields) .field("largest_niche", largest_niche) .field("variants", variants) - .field("has_repr_align", has_repr_align) + .field("repr_align", repr_align) .finish() } } @@ -1609,8 +1609,8 @@ impl<'a> Layout<'a> { self.0.0.size } - pub fn has_repr_align(self) -> bool { - self.0.0.has_repr_align + pub fn repr_align(self) -> Option { + self.0.0.repr_align } /// Whether the layout is from a type that implements [`std::marker::PointerLike`]. diff --git a/compiler/rustc_codegen_cranelift/src/abi/comments.rs b/compiler/rustc_codegen_cranelift/src/abi/comments.rs index f1ada7b7219..97f8452a468 100644 --- a/compiler/rustc_codegen_cranelift/src/abi/comments.rs +++ b/compiler/rustc_codegen_cranelift/src/abi/comments.rs @@ -83,7 +83,7 @@ pub(super) fn add_local_place_comments<'tcx>( let rustc_target::abi::LayoutS { size, align, - has_repr_align: _, + repr_align: _, abi: _, variants: _, fields: _, diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index cdf9cd8c809..ffebbab04a6 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -755,7 +755,7 @@ where largest_niche: None, align: tcx.data_layout.i8_align, size: Size::ZERO, - has_repr_align: false, + repr_align: None, }) } diff --git a/compiler/rustc_target/src/abi/call/x86.rs b/compiler/rustc_target/src/abi/call/x86.rs index 9d3f9413afd..e4292151065 100644 --- a/compiler/rustc_target/src/abi/call/x86.rs +++ b/compiler/rustc_target/src/abi/call/x86.rs @@ -63,8 +63,8 @@ where if t.is_like_msvc && arg.layout.is_adt() - && arg.layout.has_repr_align - && arg.layout.align.abi > align_4 + && let Some(repr_align) = arg.layout.repr_align + && repr_align > align_4 { // MSVC has special rules for overaligned arguments: https://reviews.llvm.org/D72114. // Summarized here: @@ -72,6 +72,10 @@ where // - For backwards compatibility, arguments with natural alignment > 4 are still passed // on stack (via `byval`). For example, this includes `double`, `int64_t`, // and structs containing them, provided they lack an explicit alignment attribute. + assert!(arg.layout.align.abi >= repr_align, + "abi alignment {:?} less than requested alignment {repr_align:?}", + arg.layout.align.abi, + ); arg.make_indirect(); } else if arg.layout.is_aggregate() { // We need to compute the alignment of the `byval` argument. The rules can be found in diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs index f693263ac95..4fbc6b9400f 100644 --- a/compiler/rustc_ty_utils/src/layout.rs +++ b/compiler/rustc_ty_utils/src/layout.rs @@ -258,7 +258,7 @@ fn layout_of_uncached<'tcx>( largest_niche, align: element.align, size, - has_repr_align: false, + repr_align: None, }) } ty::Slice(element) => { @@ -270,7 +270,7 @@ fn layout_of_uncached<'tcx>( largest_niche: None, align: element.align, size: Size::ZERO, - has_repr_align: false, + repr_align: None, }) } ty::Str => tcx.mk_layout(LayoutS { @@ -280,7 +280,7 @@ fn layout_of_uncached<'tcx>( largest_niche: None, align: dl.i8_align, size: Size::ZERO, - has_repr_align: false, + repr_align: None, }), // Odd unit types. @@ -434,7 +434,7 @@ fn layout_of_uncached<'tcx>( largest_niche: e_ly.largest_niche, size, align, - has_repr_align: false, + repr_align: None, }) } @@ -883,7 +883,7 @@ fn generator_layout<'tcx>( largest_niche: prefix.largest_niche, size, align, - has_repr_align: false, + repr_align: None, }); debug!("generator layout ({:?}): {:#?}", ty, layout); Ok(layout) diff --git a/tests/codegen/align-byval.rs b/tests/codegen/align-byval.rs index 2c64230bfd0..fc5f795bf67 100644 --- a/tests/codegen/align-byval.rs +++ b/tests/codegen/align-byval.rs @@ -71,17 +71,16 @@ pub struct ForceAlign8 { c: i64 } -// On i686-windows, this is passed by reference because alignment is requested, -// even though the requested alignment is less than the natural alignment. +// On i686-windows, this is passed on stack, because requested alignment is <=4. #[repr(C)] -#[repr(align(1))] +#[repr(align(4))] pub struct LowerFA8 { a: i64, b: i64, c: i64 } -// On i686-windows, this is passed on stack again, because the wrapper struct does not have +// On i686-windows, this is passed on stack, because the wrapper struct does not have // requested/forced alignment. #[repr(C)] pub struct WrappedFA8 { @@ -287,9 +286,7 @@ extern "C" { // i686-linux: declare void @lower_fa8({{.*}}byval(%LowerFA8) align 4{{.*}}) - // i686-windows: declare void @lower_fa8( - // i686-windows-NOT: byval - // i686-windows-SAME: align 8{{.*}}) + // i686-windows: declare void @lower_fa8({{.*}}byval(%LowerFA8) align 4{{.*}}) fn lower_fa8(x: LowerFA8); // m68k: declare void @wrapped_fa8({{.*}}byval(%WrappedFA8) align 8{{.*}}) diff --git a/tests/ui/layout/debug.stderr b/tests/ui/layout/debug.stderr index 4f27eaae8d8..99022fb11b5 100644 --- a/tests/ui/layout/debug.stderr +++ b/tests/ui/layout/debug.stderr @@ -53,7 +53,7 @@ error: layout_of(E) = Layout { variants: Single { index: 0, }, - has_repr_align: false, + repr_align: None, }, Layout { size: Size(12 bytes), @@ -78,11 +78,11 @@ error: layout_of(E) = Layout { variants: Single { index: 1, }, - has_repr_align: false, + repr_align: None, }, ], }, - has_repr_align: false, + repr_align: None, } --> $DIR/debug.rs:7:1 | @@ -127,7 +127,7 @@ error: layout_of(S) = Layout { variants: Single { index: 0, }, - has_repr_align: false, + repr_align: None, } --> $DIR/debug.rs:10:1 | @@ -150,7 +150,7 @@ error: layout_of(U) = Layout { variants: Single { index: 0, }, - has_repr_align: false, + repr_align: None, } --> $DIR/debug.rs:13:1 | @@ -242,7 +242,7 @@ error: layout_of(std::result::Result) = Layout { variants: Single { index: 0, }, - has_repr_align: false, + repr_align: None, }, Layout { size: Size(8 bytes), @@ -278,11 +278,11 @@ error: layout_of(std::result::Result) = Layout { variants: Single { index: 1, }, - has_repr_align: false, + repr_align: None, }, ], }, - has_repr_align: false, + repr_align: None, } --> $DIR/debug.rs:16:1 | @@ -309,7 +309,7 @@ error: layout_of(i32) = Layout { variants: Single { index: 0, }, - has_repr_align: false, + repr_align: None, } --> $DIR/debug.rs:19:1 | @@ -332,7 +332,7 @@ error: layout_of(V) = Layout { variants: Single { index: 0, }, - has_repr_align: false, + repr_align: None, } --> $DIR/debug.rs:22:1 | @@ -355,7 +355,7 @@ error: layout_of(W) = Layout { variants: Single { index: 0, }, - has_repr_align: false, + repr_align: None, } --> $DIR/debug.rs:28:1 | @@ -378,7 +378,7 @@ error: layout_of(Y) = Layout { variants: Single { index: 0, }, - has_repr_align: false, + repr_align: None, } --> $DIR/debug.rs:34:1 | @@ -401,7 +401,7 @@ error: layout_of(P1) = Layout { variants: Single { index: 0, }, - has_repr_align: false, + repr_align: None, } --> $DIR/debug.rs:41:1 | @@ -424,7 +424,7 @@ error: layout_of(P2) = Layout { variants: Single { index: 0, }, - has_repr_align: false, + repr_align: None, } --> $DIR/debug.rs:45:1 | @@ -447,7 +447,7 @@ error: layout_of(P3) = Layout { variants: Single { index: 0, }, - has_repr_align: false, + repr_align: None, } --> $DIR/debug.rs:53:1 | @@ -470,7 +470,7 @@ error: layout_of(P4) = Layout { variants: Single { index: 0, }, - has_repr_align: false, + repr_align: None, } --> $DIR/debug.rs:57:1 | @@ -498,7 +498,7 @@ error: layout_of(P5) = Layout { variants: Single { index: 0, }, - has_repr_align: false, + repr_align: None, } --> $DIR/debug.rs:61:1 | @@ -526,7 +526,7 @@ error: layout_of(std::mem::MaybeUninit) = Layout { variants: Single { index: 0, }, - has_repr_align: false, + repr_align: None, } --> $DIR/debug.rs:64:1 | diff --git a/tests/ui/layout/hexagon-enum.stderr b/tests/ui/layout/hexagon-enum.stderr index 08c4e547ff2..a907853585d 100644 --- a/tests/ui/layout/hexagon-enum.stderr +++ b/tests/ui/layout/hexagon-enum.stderr @@ -59,11 +59,11 @@ error: layout_of(A) = Layout { variants: Single { index: 0, }, - has_repr_align: false, + repr_align: None, }, ], }, - has_repr_align: false, + repr_align: None, } --> $DIR/hexagon-enum.rs:16:1 | @@ -131,11 +131,11 @@ error: layout_of(B) = Layout { variants: Single { index: 0, }, - has_repr_align: false, + repr_align: None, }, ], }, - has_repr_align: false, + repr_align: None, } --> $DIR/hexagon-enum.rs:20:1 | @@ -203,11 +203,11 @@ error: layout_of(C) = Layout { variants: Single { index: 0, }, - has_repr_align: false, + repr_align: None, }, ], }, - has_repr_align: false, + repr_align: None, } --> $DIR/hexagon-enum.rs:24:1 | @@ -275,11 +275,11 @@ error: layout_of(P) = Layout { variants: Single { index: 0, }, - has_repr_align: false, + repr_align: None, }, ], }, - has_repr_align: false, + repr_align: None, } --> $DIR/hexagon-enum.rs:28:1 | @@ -347,11 +347,11 @@ error: layout_of(T) = Layout { variants: Single { index: 0, }, - has_repr_align: false, + repr_align: None, }, ], }, - has_repr_align: false, + repr_align: None, } --> $DIR/hexagon-enum.rs:34:1 | diff --git a/tests/ui/layout/issue-96158-scalarpair-payload-might-be-uninit.stderr b/tests/ui/layout/issue-96158-scalarpair-payload-might-be-uninit.stderr index 5fae4d9a6a5..2db6ab9bc89 100644 --- a/tests/ui/layout/issue-96158-scalarpair-payload-might-be-uninit.stderr +++ b/tests/ui/layout/issue-96158-scalarpair-payload-might-be-uninit.stderr @@ -81,7 +81,7 @@ error: layout_of(MissingPayloadField) = Layout { variants: Single { index: 0, }, - has_repr_align: false, + repr_align: None, }, Layout { size: Size(1 bytes), @@ -100,11 +100,11 @@ error: layout_of(MissingPayloadField) = Layout { variants: Single { index: 1, }, - has_repr_align: false, + repr_align: None, }, ], }, - has_repr_align: false, + repr_align: None, } --> $DIR/issue-96158-scalarpair-payload-might-be-uninit.rs:16:1 | @@ -196,7 +196,7 @@ error: layout_of(CommonPayloadField) = Layout { variants: Single { index: 0, }, - has_repr_align: false, + repr_align: None, }, Layout { size: Size(2 bytes), @@ -232,11 +232,11 @@ error: layout_of(CommonPayloadField) = Layout { variants: Single { index: 1, }, - has_repr_align: false, + repr_align: None, }, ], }, - has_repr_align: false, + repr_align: None, } --> $DIR/issue-96158-scalarpair-payload-might-be-uninit.rs:25:1 | @@ -326,7 +326,7 @@ error: layout_of(CommonPayloadFieldIsMaybeUninit) = Layout { variants: Single { index: 0, }, - has_repr_align: false, + repr_align: None, }, Layout { size: Size(2 bytes), @@ -361,11 +361,11 @@ error: layout_of(CommonPayloadFieldIsMaybeUninit) = Layout { variants: Single { index: 1, }, - has_repr_align: false, + repr_align: None, }, ], }, - has_repr_align: false, + repr_align: None, } --> $DIR/issue-96158-scalarpair-payload-might-be-uninit.rs:33:1 | @@ -471,7 +471,7 @@ error: layout_of(NicheFirst) = Layout { variants: Single { index: 0, }, - has_repr_align: false, + repr_align: None, }, Layout { size: Size(0 bytes), @@ -490,7 +490,7 @@ error: layout_of(NicheFirst) = Layout { variants: Single { index: 1, }, - has_repr_align: false, + repr_align: None, }, Layout { size: Size(0 bytes), @@ -509,11 +509,11 @@ error: layout_of(NicheFirst) = Layout { variants: Single { index: 2, }, - has_repr_align: false, + repr_align: None, }, ], }, - has_repr_align: false, + repr_align: None, } --> $DIR/issue-96158-scalarpair-payload-might-be-uninit.rs:41:1 | @@ -619,7 +619,7 @@ error: layout_of(NicheSecond) = Layout { variants: Single { index: 0, }, - has_repr_align: false, + repr_align: None, }, Layout { size: Size(0 bytes), @@ -638,7 +638,7 @@ error: layout_of(NicheSecond) = Layout { variants: Single { index: 1, }, - has_repr_align: false, + repr_align: None, }, Layout { size: Size(0 bytes), @@ -657,11 +657,11 @@ error: layout_of(NicheSecond) = Layout { variants: Single { index: 2, }, - has_repr_align: false, + repr_align: None, }, ], }, - has_repr_align: false, + repr_align: None, } --> $DIR/issue-96158-scalarpair-payload-might-be-uninit.rs:50:1 | diff --git a/tests/ui/layout/issue-96185-overaligned-enum.stderr b/tests/ui/layout/issue-96185-overaligned-enum.stderr index fe1d4392b67..3a0ad07347d 100644 --- a/tests/ui/layout/issue-96185-overaligned-enum.stderr +++ b/tests/ui/layout/issue-96185-overaligned-enum.stderr @@ -53,7 +53,9 @@ error: layout_of(Aligned1) = Layout { variants: Single { index: 0, }, - has_repr_align: true, + repr_align: Some( + Align(8 bytes), + ), }, Layout { size: Size(8 bytes), @@ -72,11 +74,15 @@ error: layout_of(Aligned1) = Layout { variants: Single { index: 1, }, - has_repr_align: true, + repr_align: Some( + Align(8 bytes), + ), }, ], }, - has_repr_align: true, + repr_align: Some( + Align(8 bytes), + ), } --> $DIR/issue-96185-overaligned-enum.rs:8:1 | @@ -144,7 +150,9 @@ error: layout_of(Aligned2) = Layout { variants: Single { index: 0, }, - has_repr_align: true, + repr_align: Some( + Align(1 bytes), + ), }, Layout { size: Size(1 bytes), @@ -163,11 +171,15 @@ error: layout_of(Aligned2) = Layout { variants: Single { index: 1, }, - has_repr_align: true, + repr_align: Some( + Align(1 bytes), + ), }, ], }, - has_repr_align: true, + repr_align: Some( + Align(1 bytes), + ), } --> $DIR/issue-96185-overaligned-enum.rs:16:1 | diff --git a/tests/ui/layout/thumb-enum.stderr b/tests/ui/layout/thumb-enum.stderr index 7aca1aa462e..27bba72fcfe 100644 --- a/tests/ui/layout/thumb-enum.stderr +++ b/tests/ui/layout/thumb-enum.stderr @@ -59,11 +59,11 @@ error: layout_of(A) = Layout { variants: Single { index: 0, }, - has_repr_align: false, + repr_align: None, }, ], }, - has_repr_align: false, + repr_align: None, } --> $DIR/thumb-enum.rs:16:1 | @@ -131,11 +131,11 @@ error: layout_of(B) = Layout { variants: Single { index: 0, }, - has_repr_align: false, + repr_align: None, }, ], }, - has_repr_align: false, + repr_align: None, } --> $DIR/thumb-enum.rs:20:1 | @@ -203,11 +203,11 @@ error: layout_of(C) = Layout { variants: Single { index: 0, }, - has_repr_align: false, + repr_align: None, }, ], }, - has_repr_align: false, + repr_align: None, } --> $DIR/thumb-enum.rs:24:1 | @@ -275,11 +275,11 @@ error: layout_of(P) = Layout { variants: Single { index: 0, }, - has_repr_align: false, + repr_align: None, }, ], }, - has_repr_align: false, + repr_align: None, } --> $DIR/thumb-enum.rs:28:1 | @@ -347,11 +347,11 @@ error: layout_of(T) = Layout { variants: Single { index: 0, }, - has_repr_align: false, + repr_align: None, }, ], }, - has_repr_align: false, + repr_align: None, } --> $DIR/thumb-enum.rs:34:1 | diff --git a/tests/ui/layout/zero-sized-array-enum-niche.stderr b/tests/ui/layout/zero-sized-array-enum-niche.stderr index 8342d64b6fe..a9a242943ba 100644 --- a/tests/ui/layout/zero-sized-array-enum-niche.stderr +++ b/tests/ui/layout/zero-sized-array-enum-niche.stderr @@ -57,7 +57,7 @@ error: layout_of(std::result::Result<[u32; 0], bool>) = Layout { variants: Single { index: 0, }, - has_repr_align: false, + repr_align: None, }, Layout { size: Size(2 bytes), @@ -89,11 +89,11 @@ error: layout_of(std::result::Result<[u32; 0], bool>) = Layout { variants: Single { index: 1, }, - has_repr_align: false, + repr_align: None, }, ], }, - has_repr_align: false, + repr_align: None, } --> $DIR/zero-sized-array-enum-niche.rs:13:1 | @@ -159,7 +159,7 @@ error: layout_of(MultipleAlignments) = Layout { variants: Single { index: 0, }, - has_repr_align: false, + repr_align: None, }, Layout { size: Size(4 bytes), @@ -182,7 +182,7 @@ error: layout_of(MultipleAlignments) = Layout { variants: Single { index: 1, }, - has_repr_align: false, + repr_align: None, }, Layout { size: Size(2 bytes), @@ -214,11 +214,11 @@ error: layout_of(MultipleAlignments) = Layout { variants: Single { index: 2, }, - has_repr_align: false, + repr_align: None, }, ], }, - has_repr_align: false, + repr_align: None, } --> $DIR/zero-sized-array-enum-niche.rs:21:1 | @@ -284,7 +284,7 @@ error: layout_of(std::result::Result<[u32; 0], Packed>) = variants: Single { index: 0, }, - has_repr_align: false, + repr_align: None, }, Layout { size: Size(3 bytes), @@ -316,11 +316,11 @@ error: layout_of(std::result::Result<[u32; 0], Packed>) = variants: Single { index: 1, }, - has_repr_align: false, + repr_align: None, }, ], }, - has_repr_align: false, + repr_align: None, } --> $DIR/zero-sized-array-enum-niche.rs:37:1 | @@ -390,7 +390,7 @@ error: layout_of(std::result::Result<[u32; 0], Packed>) = Layout { variants: Single { index: 0, }, - has_repr_align: false, + repr_align: None, }, Layout { size: Size(2 bytes), @@ -422,11 +422,11 @@ error: layout_of(std::result::Result<[u32; 0], Packed>) = Layout { variants: Single { index: 1, }, - has_repr_align: false, + repr_align: None, }, ], }, - has_repr_align: false, + repr_align: None, } --> $DIR/zero-sized-array-enum-niche.rs:44:1 | -- cgit 1.4.1-3-g733a5 From d1e764cb3bc961a4395164a36c4e0cfd57e681a1 Mon Sep 17 00:00:00 2001 From: Erik Desjardins Date: Wed, 14 Jun 2023 22:39:11 -0400 Subject: aarch64-linux: properly handle 128bit aligned aggregates --- compiler/rustc_abi/src/layout.rs | 57 +++++++- compiler/rustc_abi/src/lib.rs | 22 ++- compiler/rustc_middle/src/ty/layout.rs | 1 + compiler/rustc_target/src/abi/call/aarch64.rs | 70 +++++----- compiler/rustc_target/src/abi/call/mod.rs | 10 +- compiler/rustc_ty_utils/src/layout.rs | 5 + tests/codegen/aarch64-struct-align-128.rs | 150 +++++++++++++++++++++ tests/run-make/extern-fn-explicit-align/test.c | 15 ++- tests/run-make/extern-fn-explicit-align/test.rs | 14 +- tests/ui/layout/debug.stderr | 18 +++ tests/ui/layout/hexagon-enum.stderr | 10 ++ ...96158-scalarpair-payload-might-be-uninit.stderr | 17 +++ .../ui/layout/issue-96185-overaligned-enum.stderr | 6 + tests/ui/layout/thumb-enum.stderr | 10 ++ tests/ui/layout/zero-sized-array-enum-niche.stderr | 13 ++ 15 files changed, 370 insertions(+), 48 deletions(-) create mode 100644 tests/codegen/aarch64-struct-align-128.rs (limited to 'tests/codegen') diff --git a/compiler/rustc_abi/src/layout.rs b/compiler/rustc_abi/src/layout.rs index ff811be3c81..75c64aabfbb 100644 --- a/compiler/rustc_abi/src/layout.rs +++ b/compiler/rustc_abi/src/layout.rs @@ -41,6 +41,7 @@ pub trait LayoutCalculator { align, size, repr_align: None, + unadjusted_abi_align: align.abi, } } @@ -124,6 +125,7 @@ pub trait LayoutCalculator { align: dl.i8_align, size: Size::ZERO, repr_align: None, + unadjusted_abi_align: dl.i8_align.abi, } } @@ -291,6 +293,8 @@ pub trait LayoutCalculator { } let mut align = dl.aggregate_align; + let mut unadjusted_abi_align = align.abi; + let mut variant_layouts = variants .iter_enumerated() .map(|(j, v)| { @@ -298,6 +302,7 @@ pub trait LayoutCalculator { st.variants = Variants::Single { index: j }; align = align.max(st.align); + unadjusted_abi_align = unadjusted_abi_align.max(st.unadjusted_abi_align); Some(st) }) @@ -425,6 +430,7 @@ pub trait LayoutCalculator { size, align, repr_align: repr.align, + unadjusted_abi_align, }; Some(TmpLayout { layout, variants: variant_layouts }) @@ -459,6 +465,8 @@ pub trait LayoutCalculator { let (min_ity, signed) = discr_range_of_repr(min, max); //Integer::repr_discr(tcx, ty, &repr, min, max); let mut align = dl.aggregate_align; + let mut unadjusted_abi_align = align.abi; + let mut size = Size::ZERO; // We're interested in the smallest alignment, so start large. @@ -501,6 +509,7 @@ pub trait LayoutCalculator { } size = cmp::max(size, st.size); align = align.max(st.align); + unadjusted_abi_align = unadjusted_abi_align.max(st.unadjusted_abi_align); Some(st) }) .collect::>>()?; @@ -695,6 +704,7 @@ pub trait LayoutCalculator { align, size, repr_align: repr.align, + unadjusted_abi_align, }; let tagged_layout = TmpLayout { layout: tagged_layout, variants: layout_variants }; @@ -735,10 +745,6 @@ pub trait LayoutCalculator { let dl = dl.borrow(); let mut align = if repr.pack.is_some() { dl.i8_align } else { dl.aggregate_align }; - if let Some(repr_align) = repr.align { - align = align.max(AbiAndPrefAlign::new(repr_align)); - } - // If all the non-ZST fields have the same ABI and union ABI optimizations aren't // disabled, we can use that common ABI for the union as a whole. struct AbiMismatch; @@ -791,6 +797,14 @@ pub trait LayoutCalculator { if let Some(pack) = repr.pack { align = align.min(AbiAndPrefAlign::new(pack)); } + // The unadjusted ABI alignment does not include repr(align), but does include repr(pack). + // See documentation on `LayoutS::unadjusted_abi_align`. + let unadjusted_abi_align = align.abi; + if let Some(repr_align) = repr.align { + align = align.max(AbiAndPrefAlign::new(repr_align)); + } + // `align` must not be modified after this, or `unadjusted_abi_align` could be inaccurate. + let align = align; // If all non-ZST fields have the same ABI, we may forward that ABI // for the union as a whole, unless otherwise inhibited. @@ -814,6 +828,7 @@ pub trait LayoutCalculator { align, size: size.align_to(align.abi), repr_align: repr.align, + unadjusted_abi_align, }) } } @@ -1023,9 +1038,16 @@ fn univariant( offset = offset.checked_add(field.size(), dl)?; } + + // The unadjusted ABI alignment does not include repr(align), but does include repr(pack). + // See documentation on `LayoutS::unadjusted_abi_align`. + let unadjusted_abi_align = align.abi; if let Some(repr_align) = repr.align { align = align.max(AbiAndPrefAlign::new(repr_align)); } + // `align` must not be modified after this point, or `unadjusted_abi_align` could be inaccurate. + let align = align; + debug!("univariant min_size: {:?}", offset); let min_size = offset; // As stated above, inverse_memory_index holds field indices by increasing offset. @@ -1111,9 +1133,29 @@ fn univariant( abi = Abi::Uninhabited; } - let repr_align = repr.align.or_else(|| { - if repr.transparent() { layout_of_single_non_zst_field?.repr_align() } else { None } - }); + let (repr_align, unadjusted_abi_align) = if repr.transparent() { + match layout_of_single_non_zst_field { + Some(l) => (l.repr_align(), l.unadjusted_abi_align()), + None => { + // `repr(transparent)` with all ZST fields. + // + // Using `None` for `repr_align` here is technically incorrect, since one of + // the ZSTs could have `repr(align(1))`. It's an interesting question, if you have + // `#{repr(transparent)] struct Foo((), ZstWithReprAlign1)`, which of those ZSTs' + // ABIs is forwarded by `repr(transparent)`? The answer to that question determines + // whether we should use `None` or `Some(align 1)` here. Thanksfully, two things + // together mean this doesn't matter: + // - You're not allowed to have a `repr(transparent)` struct that contains + // `repr(align)` > 1 ZSTs. See error E0691. + // - MSVC never treats requested align 1 differently from natural align 1. + // (And the `repr_align` field is only used on i686-windows, see `LayoutS` docs.) + // So just use `None` for now. + (None, align.abi) + } + } + } else { + (repr.align, unadjusted_abi_align) + }; Some(LayoutS { variants: Variants::Single { index: FIRST_VARIANT }, @@ -1123,6 +1165,7 @@ fn univariant( align, size, repr_align, + unadjusted_abi_align, }) } diff --git a/compiler/rustc_abi/src/lib.rs b/compiler/rustc_abi/src/lib.rs index b1577add4d0..b2138dcefae 100644 --- a/compiler/rustc_abi/src/lib.rs +++ b/compiler/rustc_abi/src/lib.rs @@ -1536,6 +1536,11 @@ pub struct LayoutS { /// Only used on i686-windows, where the argument passing ABI is different when alignment is /// requested, even if the requested alignment is equal to the natural alignment. pub repr_align: Option, + + /// The alignment the type would have, ignoring any `repr(align)` but including `repr(packed)`. + /// Only used on aarch64-linux, where the argument passing ABI ignores the requested alignment + /// in some cases. + pub unadjusted_abi_align: Align, } impl LayoutS { @@ -1551,6 +1556,7 @@ impl LayoutS { size, align, repr_align: None, + unadjusted_abi_align: align.abi, } } } @@ -1560,7 +1566,16 @@ impl fmt::Debug for LayoutS { // This is how `Layout` used to print before it become // `Interned`. We print it like this to avoid having to update // expected output in a lot of tests. - let LayoutS { size, align, abi, fields, largest_niche, variants, repr_align } = self; + let LayoutS { + size, + align, + abi, + fields, + largest_niche, + variants, + repr_align, + unadjusted_abi_align, + } = self; f.debug_struct("Layout") .field("size", size) .field("align", align) @@ -1569,6 +1584,7 @@ impl fmt::Debug for LayoutS { .field("largest_niche", largest_niche) .field("variants", variants) .field("repr_align", repr_align) + .field("unadjusted_abi_align", unadjusted_abi_align) .finish() } } @@ -1613,6 +1629,10 @@ impl<'a> Layout<'a> { self.0.0.repr_align } + pub fn unadjusted_abi_align(self) -> Align { + self.0.0.unadjusted_abi_align + } + /// Whether the layout is from a type that implements [`std::marker::PointerLike`]. /// /// Currently, that means that the type is pointer-sized, pointer-aligned, diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index ffebbab04a6..843ea64fc29 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -756,6 +756,7 @@ where align: tcx.data_layout.i8_align, size: Size::ZERO, repr_align: None, + unadjusted_abi_align: tcx.data_layout.i8_align.abi, }) } diff --git a/compiler/rustc_target/src/abi/call/aarch64.rs b/compiler/rustc_target/src/abi/call/aarch64.rs index a84988fa75c..b4c7b0f120f 100644 --- a/compiler/rustc_target/src/abi/call/aarch64.rs +++ b/compiler/rustc_target/src/abi/call/aarch64.rs @@ -1,25 +1,15 @@ use crate::abi::call::{ArgAbi, FnAbi, Reg, RegKind, Uniform}; use crate::abi::{HasDataLayout, TyAbiInterface}; -/// Given integer-types M and register width N (e.g. M=u16 and N=32 bits), the -/// `ParamExtension` policy specifies how a uM value should be treated when -/// passed via register or stack-slot of width N. See also rust-lang/rust#97463. +/// Indicates the variant of the AArch64 ABI we are compiling for. +/// Used to accommodate Apple and Microsoft's deviations from the usual AAPCS ABI. +/// +/// Corresponds to Clang's `AArch64ABIInfo::ABIKind`. #[derive(Copy, Clone, PartialEq)] -pub enum ParamExtension { - /// Indicates that when passing an i8/i16, either as a function argument or - /// as a return value, it must be sign-extended to 32 bits, and likewise a - /// u8/u16 must be zero-extended to 32-bits. (This variant is here to - /// accommodate Apple's deviation from the usual AArch64 ABI as defined by - /// ARM.) - /// - /// See also: - ExtendTo32Bits, - - /// Indicates that no sign- nor zero-extension is performed: if a value of - /// type with bitwidth M is passed as function argument or return value, - /// then M bits are copied into the least significant M bits, and the - /// remaining bits of the register (or word of memory) are untouched. - NoExtension, +pub enum AbiKind { + AAPCS, + DarwinPCS, + Win64, } fn is_homogeneous_aggregate<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>) -> Option @@ -45,15 +35,17 @@ where }) } -fn classify_ret<'a, Ty, C>(cx: &C, ret: &mut ArgAbi<'a, Ty>, param_policy: ParamExtension) +fn classify_ret<'a, Ty, C>(cx: &C, ret: &mut ArgAbi<'a, Ty>, kind: AbiKind) where Ty: TyAbiInterface<'a, C> + Copy, C: HasDataLayout, { if !ret.layout.is_aggregate() { - match param_policy { - ParamExtension::ExtendTo32Bits => ret.extend_integer_width_to(32), - ParamExtension::NoExtension => {} + if kind == AbiKind::DarwinPCS { + // On Darwin, when returning an i8/i16, it must be sign-extended to 32 bits, + // and likewise a u8/u16 must be zero-extended to 32-bits. + // See also: + ret.extend_integer_width_to(32) } return; } @@ -70,15 +62,17 @@ where ret.make_indirect(); } -fn classify_arg<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>, param_policy: ParamExtension) +fn classify_arg<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>, kind: AbiKind) where Ty: TyAbiInterface<'a, C> + Copy, C: HasDataLayout, { if !arg.layout.is_aggregate() { - match param_policy { - ParamExtension::ExtendTo32Bits => arg.extend_integer_width_to(32), - ParamExtension::NoExtension => {} + if kind == AbiKind::DarwinPCS { + // On Darwin, when passing an i8/i16, it must be sign-extended to 32 bits, + // and likewise a u8/u16 must be zero-extended to 32-bits. + // See also: + arg.extend_integer_width_to(32); } return; } @@ -87,27 +81,39 @@ where return; } let size = arg.layout.size; - let bits = size.bits(); - if bits <= 128 { - arg.cast_to(Uniform { unit: Reg::i64(), total: size }); + let align = if kind == AbiKind::AAPCS { + // When passing small aggregates by value, the AAPCS ABI mandates using the unadjusted + // alignment of the type (not including `repr(align)`). + // This matches behavior of `AArch64ABIInfo::classifyArgumentType` in Clang. + // See: + arg.layout.unadjusted_abi_align + } else { + arg.layout.align.abi + }; + if size.bits() <= 128 { + if align.bits() == 128 { + arg.cast_to(Uniform { unit: Reg::i128(), total: size }); + } else { + arg.cast_to(Uniform { unit: Reg::i64(), total: size }); + } return; } arg.make_indirect(); } -pub fn compute_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>, param_policy: ParamExtension) +pub fn compute_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>, kind: AbiKind) where Ty: TyAbiInterface<'a, C> + Copy, C: HasDataLayout, { if !fn_abi.ret.is_ignore() { - classify_ret(cx, &mut fn_abi.ret, param_policy); + classify_ret(cx, &mut fn_abi.ret, kind); } for arg in fn_abi.args.iter_mut() { if arg.is_ignore() { continue; } - classify_arg(cx, arg, param_policy); + classify_arg(cx, arg, kind); } } diff --git a/compiler/rustc_target/src/abi/call/mod.rs b/compiler/rustc_target/src/abi/call/mod.rs index c4984936cac..03e7b3e7b40 100644 --- a/compiler/rustc_target/src/abi/call/mod.rs +++ b/compiler/rustc_target/src/abi/call/mod.rs @@ -679,12 +679,14 @@ impl<'a, Ty> FnAbi<'a, Ty> { } }, "aarch64" => { - let param_policy = if cx.target_spec().is_like_osx { - aarch64::ParamExtension::ExtendTo32Bits + let kind = if cx.target_spec().is_like_osx { + aarch64::AbiKind::DarwinPCS + } else if cx.target_spec().is_like_windows { + aarch64::AbiKind::Win64 } else { - aarch64::ParamExtension::NoExtension + aarch64::AbiKind::AAPCS }; - aarch64::compute_abi_info(cx, self, param_policy) + aarch64::compute_abi_info(cx, self, kind) } "amdgpu" => amdgpu::compute_abi_info(cx, self), "arm" => arm::compute_abi_info(cx, self), diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs index 4fbc6b9400f..b8ab8baeedd 100644 --- a/compiler/rustc_ty_utils/src/layout.rs +++ b/compiler/rustc_ty_utils/src/layout.rs @@ -259,6 +259,7 @@ fn layout_of_uncached<'tcx>( align: element.align, size, repr_align: None, + unadjusted_abi_align: element.align.abi, }) } ty::Slice(element) => { @@ -271,6 +272,7 @@ fn layout_of_uncached<'tcx>( align: element.align, size: Size::ZERO, repr_align: None, + unadjusted_abi_align: element.align.abi, }) } ty::Str => tcx.mk_layout(LayoutS { @@ -281,6 +283,7 @@ fn layout_of_uncached<'tcx>( align: dl.i8_align, size: Size::ZERO, repr_align: None, + unadjusted_abi_align: dl.i8_align.abi, }), // Odd unit types. @@ -435,6 +438,7 @@ fn layout_of_uncached<'tcx>( size, align, repr_align: None, + unadjusted_abi_align: align.abi, }) } @@ -884,6 +888,7 @@ fn generator_layout<'tcx>( size, align, repr_align: None, + unadjusted_abi_align: align.abi, }); debug!("generator layout ({:?}): {:#?}", ty, layout); Ok(layout) diff --git a/tests/codegen/aarch64-struct-align-128.rs b/tests/codegen/aarch64-struct-align-128.rs new file mode 100644 index 00000000000..bf34717786d --- /dev/null +++ b/tests/codegen/aarch64-struct-align-128.rs @@ -0,0 +1,150 @@ +// Test that structs aligned to 128 bits are passed with the correct ABI on aarch64. + +// revisions:linux darwin windows +//[linux] compile-flags: --target aarch64-unknown-linux-gnu +//[darwin] compile-flags: --target aarch64-apple-darwin +//[windows] compile-flags: --target aarch64-pc-windows-msvc +//[linux] needs-llvm-components: aarch64 +//[darwin] needs-llvm-components: aarch64 +//[windows] needs-llvm-components: aarch64 + +#![feature(no_core, lang_items)] +#![crate_type = "lib"] +#![no_core] + +#[lang="sized"] +trait Sized { } +#[lang="freeze"] +trait Freeze { } +#[lang="copy"] +trait Copy { } + + + +// Passed as `[i64 x 2]`, since it's an aggregate with size <= 128 bits, align < 128 bits. +#[repr(C)] +pub struct Align8 { + pub a: u64, + pub b: u64, +} + +// repr(transparent), so same as above. +#[repr(transparent)] +pub struct Transparent8 { + a: Align8 +} + +// Passed as `[i64 x 2]`, since it's an aggregate with size <= 128 bits, align < 128 bits. +#[repr(C)] +pub struct Wrapped8 { + a: Align8, +} + +extern "C" { + // linux: declare void @test_8([2 x i64], [2 x i64], [2 x i64]) + // darwin: declare void @test_8([2 x i64], [2 x i64], [2 x i64]) + // windows: declare void @test_8([2 x i64], [2 x i64], [2 x i64]) + fn test_8(a: Align8, b: Transparent8, c: Wrapped8); +} + + + +// Passed as `i128`, since it's an aggregate with size <= 128 bits, align = 128 bits. +// EXCEPT on Linux, where there's a special case to use its unadjusted alignment, +// making it the same as `Align8`, so it's be passed as `[i64 x 2]`. +#[repr(C)] +#[repr(align(16))] +pub struct Align16 { + pub a: u64, + pub b: u64, +} + +// repr(transparent), so same as above. +#[repr(transparent)] +pub struct Transparent16 { + a: Align16 +} + +// Passed as `i128`, since it's an aggregate with size <= 128 bits, align = 128 bits. +// On Linux, the "unadjustedness" doesn't recurse into fields, so this is passed as `i128`. +#[repr(C)] +pub struct Wrapped16 { + pub a: Align16, +} + +extern "C" { + // linux: declare void @test_16([2 x i64], [2 x i64], i128) + // darwin: declare void @test_16(i128, i128, i128) + // windows: declare void @test_16(i128, i128, i128) + fn test_16(a: Align16, b: Transparent16, c: Wrapped16); +} + + + +// Passed as `i128`, since it's an aggregate with size <= 128 bits, align = 128 bits. +#[repr(C)] +pub struct I128 { + pub a: i128, +} + +// repr(transparent), so same as above. +#[repr(transparent)] +pub struct TransparentI128 { + a: I128 +} + +// Passed as `i128`, since it's an aggregate with size <= 128 bits, align = 128 bits. +#[repr(C)] +pub struct WrappedI128 { + pub a: I128 +} + +extern "C" { + // linux: declare void @test_i128(i128, i128, i128) + // darwin: declare void @test_i128(i128, i128, i128) + // windows: declare void @test_i128(i128, i128, i128) + fn test_i128(a: I128, b: TransparentI128, c: WrappedI128); +} + + + +// Passed as `[2 x i64]`, since it's an aggregate with size <= 128 bits, align < 128 bits. +// Note that the Linux special case does not apply, because packing is not considered "adjustment". +#[repr(C)] +#[repr(packed)] +pub struct Packed { + pub a: i128, +} + +// repr(transparent), so same as above. +#[repr(transparent)] +pub struct TransparentPacked { + a: Packed +} + +// Passed as `[2 x i64]`, since it's an aggregate with size <= 128 bits, align < 128 bits. +#[repr(C)] +pub struct WrappedPacked { + pub a: Packed +} + +extern "C" { + // linux: declare void @test_packed([2 x i64], [2 x i64], [2 x i64]) + // darwin: declare void @test_packed([2 x i64], [2 x i64], [2 x i64]) + // windows: declare void @test_packed([2 x i64], [2 x i64], [2 x i64]) + fn test_packed(a: Packed, b: TransparentPacked, c: WrappedPacked); +} + + + +pub unsafe fn main( + a1: Align8, a2: Transparent8, a3: Wrapped8, + b1: Align16, b2: Transparent16, b3: Wrapped16, + c1: I128, c2: TransparentI128, c3: WrappedI128, + d1: Packed, d2: TransparentPacked, d3: WrappedPacked, +) { + test_8(a1, a2, a3); + test_16(b1, b2, b3); + test_i128(c1, c2, c3); + test_packed(d1, d2, d3); +} diff --git a/tests/run-make/extern-fn-explicit-align/test.c b/tests/run-make/extern-fn-explicit-align/test.c index 292e7a822b5..8d20864326b 100644 --- a/tests/run-make/extern-fn-explicit-align/test.c +++ b/tests/run-make/extern-fn-explicit-align/test.c @@ -44,7 +44,12 @@ struct __attribute__((aligned(1))) LowerAlign }; #endif - +#pragma pack(push, 1) +struct Packed +{ + __uint128_t a; +}; +#pragma pack(pop) int32_t many_args( void *a, @@ -59,7 +64,9 @@ int32_t many_args( struct WrappedU64s j, void *k, struct LowerAlign l, - const char *m) + void *m, + struct Packed n, + const char *o) { assert(!a); assert(!b); @@ -77,6 +84,8 @@ int32_t many_args( assert(!k); assert(l.a == 5); assert(l.b == 6); - assert(strcmp(m, "Hello world") == 0); + assert(!m); + assert(n.a == 7); + assert(strcmp(o, "Hello world") == 0); return 0; } diff --git a/tests/run-make/extern-fn-explicit-align/test.rs b/tests/run-make/extern-fn-explicit-align/test.rs index c5b3e24048e..56c6437dad2 100644 --- a/tests/run-make/extern-fn-explicit-align/test.rs +++ b/tests/run-make/extern-fn-explicit-align/test.rs @@ -34,6 +34,13 @@ pub struct LowerAlign { pub b: u64, } +#[derive(Copy, Clone)] +#[repr(C)] +#[repr(packed)] +pub struct Packed { + pub a: u128 +} + #[link(name = "test", kind = "static")] extern "C" { fn many_args( @@ -49,7 +56,9 @@ extern "C" { j: WrappedU64s, k: *mut (), l: LowerAlign, - m: *const c_char, + m: *mut (), + n: Packed, + o: *const c_char, ) -> i32; } @@ -60,6 +69,7 @@ fn main() { let two_u64s = TwoU64s { a: 1, b: 2 }; let wrapped = WrappedU64s { a: TwoU64s { a: 3, b: 4 } }; let lower = LowerAlign { a: 5, b: 6 }; + let packed = Packed { a: 7 }; let string = STRING; unsafe { many_args( @@ -75,6 +85,8 @@ fn main() { wrapped, null_mut(), lower, + null_mut(), + packed, string.as_ptr(), ); } diff --git a/tests/ui/layout/debug.stderr b/tests/ui/layout/debug.stderr index 99022fb11b5..1bf89d0dcb3 100644 --- a/tests/ui/layout/debug.stderr +++ b/tests/ui/layout/debug.stderr @@ -54,6 +54,7 @@ error: layout_of(E) = Layout { index: 0, }, repr_align: None, + unadjusted_abi_align: Align(1 bytes), }, Layout { size: Size(12 bytes), @@ -79,10 +80,12 @@ error: layout_of(E) = Layout { index: 1, }, repr_align: None, + unadjusted_abi_align: Align(4 bytes), }, ], }, repr_align: None, + unadjusted_abi_align: Align(4 bytes), } --> $DIR/debug.rs:7:1 | @@ -128,6 +131,7 @@ error: layout_of(S) = Layout { index: 0, }, repr_align: None, + unadjusted_abi_align: Align(4 bytes), } --> $DIR/debug.rs:10:1 | @@ -151,6 +155,7 @@ error: layout_of(U) = Layout { index: 0, }, repr_align: None, + unadjusted_abi_align: Align(4 bytes), } --> $DIR/debug.rs:13:1 | @@ -243,6 +248,7 @@ error: layout_of(std::result::Result) = Layout { index: 0, }, repr_align: None, + unadjusted_abi_align: Align(4 bytes), }, Layout { size: Size(8 bytes), @@ -279,10 +285,12 @@ error: layout_of(std::result::Result) = Layout { index: 1, }, repr_align: None, + unadjusted_abi_align: Align(4 bytes), }, ], }, repr_align: None, + unadjusted_abi_align: Align(4 bytes), } --> $DIR/debug.rs:16:1 | @@ -310,6 +318,7 @@ error: layout_of(i32) = Layout { index: 0, }, repr_align: None, + unadjusted_abi_align: Align(4 bytes), } --> $DIR/debug.rs:19:1 | @@ -333,6 +342,7 @@ error: layout_of(V) = Layout { index: 0, }, repr_align: None, + unadjusted_abi_align: Align(2 bytes), } --> $DIR/debug.rs:22:1 | @@ -356,6 +366,7 @@ error: layout_of(W) = Layout { index: 0, }, repr_align: None, + unadjusted_abi_align: Align(2 bytes), } --> $DIR/debug.rs:28:1 | @@ -379,6 +390,7 @@ error: layout_of(Y) = Layout { index: 0, }, repr_align: None, + unadjusted_abi_align: Align(2 bytes), } --> $DIR/debug.rs:34:1 | @@ -402,6 +414,7 @@ error: layout_of(P1) = Layout { index: 0, }, repr_align: None, + unadjusted_abi_align: Align(1 bytes), } --> $DIR/debug.rs:41:1 | @@ -425,6 +438,7 @@ error: layout_of(P2) = Layout { index: 0, }, repr_align: None, + unadjusted_abi_align: Align(1 bytes), } --> $DIR/debug.rs:45:1 | @@ -448,6 +462,7 @@ error: layout_of(P3) = Layout { index: 0, }, repr_align: None, + unadjusted_abi_align: Align(1 bytes), } --> $DIR/debug.rs:53:1 | @@ -471,6 +486,7 @@ error: layout_of(P4) = Layout { index: 0, }, repr_align: None, + unadjusted_abi_align: Align(1 bytes), } --> $DIR/debug.rs:57:1 | @@ -499,6 +515,7 @@ error: layout_of(P5) = Layout { index: 0, }, repr_align: None, + unadjusted_abi_align: Align(1 bytes), } --> $DIR/debug.rs:61:1 | @@ -527,6 +544,7 @@ error: layout_of(std::mem::MaybeUninit) = Layout { index: 0, }, repr_align: None, + unadjusted_abi_align: Align(1 bytes), } --> $DIR/debug.rs:64:1 | diff --git a/tests/ui/layout/hexagon-enum.stderr b/tests/ui/layout/hexagon-enum.stderr index a907853585d..acc97672d3c 100644 --- a/tests/ui/layout/hexagon-enum.stderr +++ b/tests/ui/layout/hexagon-enum.stderr @@ -60,10 +60,12 @@ error: layout_of(A) = Layout { index: 0, }, repr_align: None, + unadjusted_abi_align: Align(1 bytes), }, ], }, repr_align: None, + unadjusted_abi_align: Align(1 bytes), } --> $DIR/hexagon-enum.rs:16:1 | @@ -132,10 +134,12 @@ error: layout_of(B) = Layout { index: 0, }, repr_align: None, + unadjusted_abi_align: Align(1 bytes), }, ], }, repr_align: None, + unadjusted_abi_align: Align(1 bytes), } --> $DIR/hexagon-enum.rs:20:1 | @@ -204,10 +208,12 @@ error: layout_of(C) = Layout { index: 0, }, repr_align: None, + unadjusted_abi_align: Align(2 bytes), }, ], }, repr_align: None, + unadjusted_abi_align: Align(2 bytes), } --> $DIR/hexagon-enum.rs:24:1 | @@ -276,10 +282,12 @@ error: layout_of(P) = Layout { index: 0, }, repr_align: None, + unadjusted_abi_align: Align(4 bytes), }, ], }, repr_align: None, + unadjusted_abi_align: Align(4 bytes), } --> $DIR/hexagon-enum.rs:28:1 | @@ -348,10 +356,12 @@ error: layout_of(T) = Layout { index: 0, }, repr_align: None, + unadjusted_abi_align: Align(4 bytes), }, ], }, repr_align: None, + unadjusted_abi_align: Align(4 bytes), } --> $DIR/hexagon-enum.rs:34:1 | diff --git a/tests/ui/layout/issue-96158-scalarpair-payload-might-be-uninit.stderr b/tests/ui/layout/issue-96158-scalarpair-payload-might-be-uninit.stderr index 2db6ab9bc89..6e013af199d 100644 --- a/tests/ui/layout/issue-96158-scalarpair-payload-might-be-uninit.stderr +++ b/tests/ui/layout/issue-96158-scalarpair-payload-might-be-uninit.stderr @@ -82,6 +82,7 @@ error: layout_of(MissingPayloadField) = Layout { index: 0, }, repr_align: None, + unadjusted_abi_align: Align(1 bytes), }, Layout { size: Size(1 bytes), @@ -101,10 +102,12 @@ error: layout_of(MissingPayloadField) = Layout { index: 1, }, repr_align: None, + unadjusted_abi_align: Align(1 bytes), }, ], }, repr_align: None, + unadjusted_abi_align: Align(1 bytes), } --> $DIR/issue-96158-scalarpair-payload-might-be-uninit.rs:16:1 | @@ -197,6 +200,7 @@ error: layout_of(CommonPayloadField) = Layout { index: 0, }, repr_align: None, + unadjusted_abi_align: Align(1 bytes), }, Layout { size: Size(2 bytes), @@ -233,10 +237,12 @@ error: layout_of(CommonPayloadField) = Layout { index: 1, }, repr_align: None, + unadjusted_abi_align: Align(1 bytes), }, ], }, repr_align: None, + unadjusted_abi_align: Align(1 bytes), } --> $DIR/issue-96158-scalarpair-payload-might-be-uninit.rs:25:1 | @@ -327,6 +333,7 @@ error: layout_of(CommonPayloadFieldIsMaybeUninit) = Layout { index: 0, }, repr_align: None, + unadjusted_abi_align: Align(1 bytes), }, Layout { size: Size(2 bytes), @@ -362,10 +369,12 @@ error: layout_of(CommonPayloadFieldIsMaybeUninit) = Layout { index: 1, }, repr_align: None, + unadjusted_abi_align: Align(1 bytes), }, ], }, repr_align: None, + unadjusted_abi_align: Align(1 bytes), } --> $DIR/issue-96158-scalarpair-payload-might-be-uninit.rs:33:1 | @@ -472,6 +481,7 @@ error: layout_of(NicheFirst) = Layout { index: 0, }, repr_align: None, + unadjusted_abi_align: Align(1 bytes), }, Layout { size: Size(0 bytes), @@ -491,6 +501,7 @@ error: layout_of(NicheFirst) = Layout { index: 1, }, repr_align: None, + unadjusted_abi_align: Align(1 bytes), }, Layout { size: Size(0 bytes), @@ -510,10 +521,12 @@ error: layout_of(NicheFirst) = Layout { index: 2, }, repr_align: None, + unadjusted_abi_align: Align(1 bytes), }, ], }, repr_align: None, + unadjusted_abi_align: Align(1 bytes), } --> $DIR/issue-96158-scalarpair-payload-might-be-uninit.rs:41:1 | @@ -620,6 +633,7 @@ error: layout_of(NicheSecond) = Layout { index: 0, }, repr_align: None, + unadjusted_abi_align: Align(1 bytes), }, Layout { size: Size(0 bytes), @@ -639,6 +653,7 @@ error: layout_of(NicheSecond) = Layout { index: 1, }, repr_align: None, + unadjusted_abi_align: Align(1 bytes), }, Layout { size: Size(0 bytes), @@ -658,10 +673,12 @@ error: layout_of(NicheSecond) = Layout { index: 2, }, repr_align: None, + unadjusted_abi_align: Align(1 bytes), }, ], }, repr_align: None, + unadjusted_abi_align: Align(1 bytes), } --> $DIR/issue-96158-scalarpair-payload-might-be-uninit.rs:50:1 | diff --git a/tests/ui/layout/issue-96185-overaligned-enum.stderr b/tests/ui/layout/issue-96185-overaligned-enum.stderr index 3a0ad07347d..ef6cc79eedb 100644 --- a/tests/ui/layout/issue-96185-overaligned-enum.stderr +++ b/tests/ui/layout/issue-96185-overaligned-enum.stderr @@ -56,6 +56,7 @@ error: layout_of(Aligned1) = Layout { repr_align: Some( Align(8 bytes), ), + unadjusted_abi_align: Align(1 bytes), }, Layout { size: Size(8 bytes), @@ -77,12 +78,14 @@ error: layout_of(Aligned1) = Layout { repr_align: Some( Align(8 bytes), ), + unadjusted_abi_align: Align(1 bytes), }, ], }, repr_align: Some( Align(8 bytes), ), + unadjusted_abi_align: Align(1 bytes), } --> $DIR/issue-96185-overaligned-enum.rs:8:1 | @@ -153,6 +156,7 @@ error: layout_of(Aligned2) = Layout { repr_align: Some( Align(1 bytes), ), + unadjusted_abi_align: Align(1 bytes), }, Layout { size: Size(1 bytes), @@ -174,12 +178,14 @@ error: layout_of(Aligned2) = Layout { repr_align: Some( Align(1 bytes), ), + unadjusted_abi_align: Align(1 bytes), }, ], }, repr_align: Some( Align(1 bytes), ), + unadjusted_abi_align: Align(1 bytes), } --> $DIR/issue-96185-overaligned-enum.rs:16:1 | diff --git a/tests/ui/layout/thumb-enum.stderr b/tests/ui/layout/thumb-enum.stderr index 27bba72fcfe..c1837b0e47e 100644 --- a/tests/ui/layout/thumb-enum.stderr +++ b/tests/ui/layout/thumb-enum.stderr @@ -60,10 +60,12 @@ error: layout_of(A) = Layout { index: 0, }, repr_align: None, + unadjusted_abi_align: Align(1 bytes), }, ], }, repr_align: None, + unadjusted_abi_align: Align(1 bytes), } --> $DIR/thumb-enum.rs:16:1 | @@ -132,10 +134,12 @@ error: layout_of(B) = Layout { index: 0, }, repr_align: None, + unadjusted_abi_align: Align(1 bytes), }, ], }, repr_align: None, + unadjusted_abi_align: Align(1 bytes), } --> $DIR/thumb-enum.rs:20:1 | @@ -204,10 +208,12 @@ error: layout_of(C) = Layout { index: 0, }, repr_align: None, + unadjusted_abi_align: Align(2 bytes), }, ], }, repr_align: None, + unadjusted_abi_align: Align(2 bytes), } --> $DIR/thumb-enum.rs:24:1 | @@ -276,10 +282,12 @@ error: layout_of(P) = Layout { index: 0, }, repr_align: None, + unadjusted_abi_align: Align(4 bytes), }, ], }, repr_align: None, + unadjusted_abi_align: Align(4 bytes), } --> $DIR/thumb-enum.rs:28:1 | @@ -348,10 +356,12 @@ error: layout_of(T) = Layout { index: 0, }, repr_align: None, + unadjusted_abi_align: Align(4 bytes), }, ], }, repr_align: None, + unadjusted_abi_align: Align(4 bytes), } --> $DIR/thumb-enum.rs:34:1 | diff --git a/tests/ui/layout/zero-sized-array-enum-niche.stderr b/tests/ui/layout/zero-sized-array-enum-niche.stderr index a9a242943ba..02bf9d496bc 100644 --- a/tests/ui/layout/zero-sized-array-enum-niche.stderr +++ b/tests/ui/layout/zero-sized-array-enum-niche.stderr @@ -58,6 +58,7 @@ error: layout_of(std::result::Result<[u32; 0], bool>) = Layout { index: 0, }, repr_align: None, + unadjusted_abi_align: Align(4 bytes), }, Layout { size: Size(2 bytes), @@ -90,10 +91,12 @@ error: layout_of(std::result::Result<[u32; 0], bool>) = Layout { index: 1, }, repr_align: None, + unadjusted_abi_align: Align(1 bytes), }, ], }, repr_align: None, + unadjusted_abi_align: Align(4 bytes), } --> $DIR/zero-sized-array-enum-niche.rs:13:1 | @@ -160,6 +163,7 @@ error: layout_of(MultipleAlignments) = Layout { index: 0, }, repr_align: None, + unadjusted_abi_align: Align(2 bytes), }, Layout { size: Size(4 bytes), @@ -183,6 +187,7 @@ error: layout_of(MultipleAlignments) = Layout { index: 1, }, repr_align: None, + unadjusted_abi_align: Align(4 bytes), }, Layout { size: Size(2 bytes), @@ -215,10 +220,12 @@ error: layout_of(MultipleAlignments) = Layout { index: 2, }, repr_align: None, + unadjusted_abi_align: Align(1 bytes), }, ], }, repr_align: None, + unadjusted_abi_align: Align(4 bytes), } --> $DIR/zero-sized-array-enum-niche.rs:21:1 | @@ -285,6 +292,7 @@ error: layout_of(std::result::Result<[u32; 0], Packed>) = index: 0, }, repr_align: None, + unadjusted_abi_align: Align(4 bytes), }, Layout { size: Size(3 bytes), @@ -317,10 +325,12 @@ error: layout_of(std::result::Result<[u32; 0], Packed>) = index: 1, }, repr_align: None, + unadjusted_abi_align: Align(1 bytes), }, ], }, repr_align: None, + unadjusted_abi_align: Align(4 bytes), } --> $DIR/zero-sized-array-enum-niche.rs:37:1 | @@ -391,6 +401,7 @@ error: layout_of(std::result::Result<[u32; 0], Packed>) = Layout { index: 0, }, repr_align: None, + unadjusted_abi_align: Align(4 bytes), }, Layout { size: Size(2 bytes), @@ -423,10 +434,12 @@ error: layout_of(std::result::Result<[u32; 0], Packed>) = Layout { index: 1, }, repr_align: None, + unadjusted_abi_align: Align(1 bytes), }, ], }, repr_align: None, + unadjusted_abi_align: Align(4 bytes), } --> $DIR/zero-sized-array-enum-niche.rs:44:1 | -- cgit 1.4.1-3-g733a5 From 571aac9fba027513e0d4178b379f815c38fc0fd1 Mon Sep 17 00:00:00 2001 From: Jubilee Young Date: Tue, 11 Jul 2023 17:43:51 -0700 Subject: Add mir-opt3 rev to simd-wide-sum test --- tests/codegen/simd-wide-sum.rs | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'tests/codegen') diff --git a/tests/codegen/simd-wide-sum.rs b/tests/codegen/simd-wide-sum.rs index db2aa20bde7..87ef29b351f 100644 --- a/tests/codegen/simd-wide-sum.rs +++ b/tests/codegen/simd-wide-sum.rs @@ -1,6 +1,11 @@ +// revisions: llvm mir-opt3 // compile-flags: -C opt-level=3 -Z merge-functions=disabled --edition=2021 // only-x86_64 // ignore-debug: the debug assertions get in the way +// [mir-opt3]compile-flags: -Zmir-opt-level=3 +// [mir-opt3]build-pass + +// mir-opt3 is a regression test for https://github.com/rust-lang/rust/issues/98016 #![crate_type = "lib"] #![feature(portable_simd)] -- cgit 1.4.1-3-g733a5 From 7dc049c378743a9e60dccf47143df9c0052bfe2b Mon Sep 17 00:00:00 2001 From: Jubilee Young Date: Tue, 11 Jul 2023 19:17:56 -0700 Subject: Reenable all cases of simd-wide-sum --- tests/codegen/simd-wide-sum.rs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'tests/codegen') diff --git a/tests/codegen/simd-wide-sum.rs b/tests/codegen/simd-wide-sum.rs index 87ef29b351f..3116f9597bc 100644 --- a/tests/codegen/simd-wide-sum.rs +++ b/tests/codegen/simd-wide-sum.rs @@ -52,9 +52,8 @@ pub fn wider_reduce_iter(x: Simd) -> u16 { #[no_mangle] // CHECK-LABEL: @wider_reduce_into_iter pub fn wider_reduce_into_iter(x: Simd) -> u16 { - // FIXME MIR inlining messes up LLVM optimizations. - // WOULD-CHECK: zext <8 x i8> - // WOULD-CHECK-SAME: to <8 x i16> - // WOULD-CHECK: call i16 @llvm.vector.reduce.add.v8i16(<8 x i16> + // CHECK: zext <8 x i8> + // CHECK-SAME: to <8 x i16> + // CHECK: call i16 @llvm.vector.reduce.add.v8i16(<8 x i16> x.to_array().into_iter().map(u16::from).sum() } -- cgit 1.4.1-3-g733a5 From f993c6d73e3edfd362620b72799a53e4a96ae775 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Fri, 14 Jul 2023 12:37:29 +0000 Subject: Bless codegen test. --- tests/codegen/iter-repeat-n-trivial-drop.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tests/codegen') diff --git a/tests/codegen/iter-repeat-n-trivial-drop.rs b/tests/codegen/iter-repeat-n-trivial-drop.rs index 24059f190ac..65a0f7e7ffb 100644 --- a/tests/codegen/iter-repeat-n-trivial-drop.rs +++ b/tests/codegen/iter-repeat-n-trivial-drop.rs @@ -33,7 +33,7 @@ pub fn iter_repeat_n_next(it: &mut std::iter::RepeatN) -> Option Date: Fri, 14 Jul 2023 17:48:13 -0400 Subject: i686-windows: make requested alignment > 4 special case apply transitively --- compiler/rustc_abi/src/layout.rs | 40 ++++++++++------------ compiler/rustc_abi/src/lib.rs | 14 ++++---- compiler/rustc_middle/src/ty/layout.rs | 2 +- compiler/rustc_target/src/abi/call/x86.rs | 8 ++--- compiler/rustc_ty_utils/src/layout.rs | 10 +++--- tests/codegen/align-byval.rs | 6 ++-- tests/ui/layout/debug.stderr | 36 +++++++++---------- tests/ui/layout/hexagon-enum.stderr | 20 +++++------ ...96158-scalarpair-payload-might-be-uninit.stderr | 34 +++++++++--------- .../ui/layout/issue-96185-overaligned-enum.stderr | 12 +++---- tests/ui/layout/thumb-enum.stderr | 20 +++++------ tests/ui/layout/zero-sized-array-enum-niche.stderr | 26 +++++++------- 12 files changed, 113 insertions(+), 115 deletions(-) (limited to 'tests/codegen') diff --git a/compiler/rustc_abi/src/layout.rs b/compiler/rustc_abi/src/layout.rs index 75c64aabfbb..aea88641f82 100644 --- a/compiler/rustc_abi/src/layout.rs +++ b/compiler/rustc_abi/src/layout.rs @@ -40,7 +40,7 @@ pub trait LayoutCalculator { largest_niche, align, size, - repr_align: None, + max_repr_align: None, unadjusted_abi_align: align.abi, } } @@ -124,7 +124,7 @@ pub trait LayoutCalculator { largest_niche: None, align: dl.i8_align, size: Size::ZERO, - repr_align: None, + max_repr_align: None, unadjusted_abi_align: dl.i8_align.abi, } } @@ -293,6 +293,7 @@ pub trait LayoutCalculator { } let mut align = dl.aggregate_align; + let mut max_repr_align = repr.align; let mut unadjusted_abi_align = align.abi; let mut variant_layouts = variants @@ -302,6 +303,7 @@ pub trait LayoutCalculator { st.variants = Variants::Single { index: j }; align = align.max(st.align); + max_repr_align = max_repr_align.max(st.max_repr_align); unadjusted_abi_align = unadjusted_abi_align.max(st.unadjusted_abi_align); Some(st) @@ -429,7 +431,7 @@ pub trait LayoutCalculator { largest_niche, size, align, - repr_align: repr.align, + max_repr_align, unadjusted_abi_align, }; @@ -465,6 +467,7 @@ pub trait LayoutCalculator { let (min_ity, signed) = discr_range_of_repr(min, max); //Integer::repr_discr(tcx, ty, &repr, min, max); let mut align = dl.aggregate_align; + let mut max_repr_align = repr.align; let mut unadjusted_abi_align = align.abi; let mut size = Size::ZERO; @@ -509,6 +512,7 @@ pub trait LayoutCalculator { } size = cmp::max(size, st.size); align = align.max(st.align); + max_repr_align = max_repr_align.max(st.max_repr_align); unadjusted_abi_align = unadjusted_abi_align.max(st.unadjusted_abi_align); Some(st) }) @@ -703,7 +707,7 @@ pub trait LayoutCalculator { abi, align, size, - repr_align: repr.align, + max_repr_align, unadjusted_abi_align, }; @@ -744,6 +748,7 @@ pub trait LayoutCalculator { let dl = self.current_data_layout(); let dl = dl.borrow(); let mut align = if repr.pack.is_some() { dl.i8_align } else { dl.aggregate_align }; + let mut max_repr_align = repr.align; // If all the non-ZST fields have the same ABI and union ABI optimizations aren't // disabled, we can use that common ABI for the union as a whole. @@ -761,6 +766,7 @@ pub trait LayoutCalculator { assert!(field.0.is_sized()); align = align.max(field.align()); + max_repr_align = max_repr_align.max(field.max_repr_align()); size = cmp::max(size, field.size()); if field.0.is_zst() { @@ -827,7 +833,7 @@ pub trait LayoutCalculator { largest_niche: None, align, size: size.align_to(align.abi), - repr_align: repr.align, + max_repr_align, unadjusted_abi_align, }) } @@ -849,6 +855,7 @@ fn univariant( ) -> Option { let pack = repr.pack; let mut align = if pack.is_some() { dl.i8_align } else { dl.aggregate_align }; + let mut max_repr_align = repr.align; let mut inverse_memory_index: IndexVec = fields.indices().collect(); let optimize = !repr.inhibit_struct_field_reordering_opt(); if optimize && fields.len() > 1 { @@ -1017,6 +1024,7 @@ fn univariant( }; offset = offset.align_to(field_align.abi); align = align.max(field_align); + max_repr_align = max_repr_align.max(field.max_repr_align()); debug!("univariant offset: {:?} field: {:#?}", offset, field); offsets[i] = offset; @@ -1133,28 +1141,16 @@ fn univariant( abi = Abi::Uninhabited; } - let (repr_align, unadjusted_abi_align) = if repr.transparent() { + let unadjusted_abi_align = if repr.transparent() { match layout_of_single_non_zst_field { - Some(l) => (l.repr_align(), l.unadjusted_abi_align()), + Some(l) => l.unadjusted_abi_align(), None => { // `repr(transparent)` with all ZST fields. - // - // Using `None` for `repr_align` here is technically incorrect, since one of - // the ZSTs could have `repr(align(1))`. It's an interesting question, if you have - // `#{repr(transparent)] struct Foo((), ZstWithReprAlign1)`, which of those ZSTs' - // ABIs is forwarded by `repr(transparent)`? The answer to that question determines - // whether we should use `None` or `Some(align 1)` here. Thanksfully, two things - // together mean this doesn't matter: - // - You're not allowed to have a `repr(transparent)` struct that contains - // `repr(align)` > 1 ZSTs. See error E0691. - // - MSVC never treats requested align 1 differently from natural align 1. - // (And the `repr_align` field is only used on i686-windows, see `LayoutS` docs.) - // So just use `None` for now. - (None, align.abi) + align.abi } } } else { - (repr.align, unadjusted_abi_align) + unadjusted_abi_align }; Some(LayoutS { @@ -1164,7 +1160,7 @@ fn univariant( largest_niche, align, size, - repr_align, + max_repr_align, unadjusted_abi_align, }) } diff --git a/compiler/rustc_abi/src/lib.rs b/compiler/rustc_abi/src/lib.rs index b2138dcefae..ef0c763ac20 100644 --- a/compiler/rustc_abi/src/lib.rs +++ b/compiler/rustc_abi/src/lib.rs @@ -1532,10 +1532,10 @@ pub struct LayoutS { pub align: AbiAndPrefAlign, pub size: Size, - /// The alignment explicitly requested with `repr(align)`. + /// The largest alignment explicitly requested with `repr(align)` on this type or any field. /// Only used on i686-windows, where the argument passing ABI is different when alignment is /// requested, even if the requested alignment is equal to the natural alignment. - pub repr_align: Option, + pub max_repr_align: Option, /// The alignment the type would have, ignoring any `repr(align)` but including `repr(packed)`. /// Only used on aarch64-linux, where the argument passing ABI ignores the requested alignment @@ -1555,7 +1555,7 @@ impl LayoutS { largest_niche, size, align, - repr_align: None, + max_repr_align: None, unadjusted_abi_align: align.abi, } } @@ -1573,7 +1573,7 @@ impl fmt::Debug for LayoutS { fields, largest_niche, variants, - repr_align, + max_repr_align, unadjusted_abi_align, } = self; f.debug_struct("Layout") @@ -1583,7 +1583,7 @@ impl fmt::Debug for LayoutS { .field("fields", fields) .field("largest_niche", largest_niche) .field("variants", variants) - .field("repr_align", repr_align) + .field("max_repr_align", max_repr_align) .field("unadjusted_abi_align", unadjusted_abi_align) .finish() } @@ -1625,8 +1625,8 @@ impl<'a> Layout<'a> { self.0.0.size } - pub fn repr_align(self) -> Option { - self.0.0.repr_align + pub fn max_repr_align(self) -> Option { + self.0.0.max_repr_align } pub fn unadjusted_abi_align(self) -> Align { diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index 843ea64fc29..f8c56e5abb8 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -755,7 +755,7 @@ where largest_niche: None, align: tcx.data_layout.i8_align, size: Size::ZERO, - repr_align: None, + max_repr_align: None, unadjusted_abi_align: tcx.data_layout.i8_align.abi, }) } diff --git a/compiler/rustc_target/src/abi/call/x86.rs b/compiler/rustc_target/src/abi/call/x86.rs index e4292151065..b738c3133d9 100644 --- a/compiler/rustc_target/src/abi/call/x86.rs +++ b/compiler/rustc_target/src/abi/call/x86.rs @@ -63,8 +63,8 @@ where if t.is_like_msvc && arg.layout.is_adt() - && let Some(repr_align) = arg.layout.repr_align - && repr_align > align_4 + && let Some(max_repr_align) = arg.layout.max_repr_align + && max_repr_align > align_4 { // MSVC has special rules for overaligned arguments: https://reviews.llvm.org/D72114. // Summarized here: @@ -72,8 +72,8 @@ where // - For backwards compatibility, arguments with natural alignment > 4 are still passed // on stack (via `byval`). For example, this includes `double`, `int64_t`, // and structs containing them, provided they lack an explicit alignment attribute. - assert!(arg.layout.align.abi >= repr_align, - "abi alignment {:?} less than requested alignment {repr_align:?}", + assert!(arg.layout.align.abi >= max_repr_align, + "abi alignment {:?} less than requested alignment {max_repr_align:?}", arg.layout.align.abi, ); arg.make_indirect(); diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs index b8ab8baeedd..74b484bd85a 100644 --- a/compiler/rustc_ty_utils/src/layout.rs +++ b/compiler/rustc_ty_utils/src/layout.rs @@ -258,7 +258,7 @@ fn layout_of_uncached<'tcx>( largest_niche, align: element.align, size, - repr_align: None, + max_repr_align: None, unadjusted_abi_align: element.align.abi, }) } @@ -271,7 +271,7 @@ fn layout_of_uncached<'tcx>( largest_niche: None, align: element.align, size: Size::ZERO, - repr_align: None, + max_repr_align: None, unadjusted_abi_align: element.align.abi, }) } @@ -282,7 +282,7 @@ fn layout_of_uncached<'tcx>( largest_niche: None, align: dl.i8_align, size: Size::ZERO, - repr_align: None, + max_repr_align: None, unadjusted_abi_align: dl.i8_align.abi, }), @@ -437,7 +437,7 @@ fn layout_of_uncached<'tcx>( largest_niche: e_ly.largest_niche, size, align, - repr_align: None, + max_repr_align: None, unadjusted_abi_align: align.abi, }) } @@ -887,7 +887,7 @@ fn generator_layout<'tcx>( largest_niche: prefix.largest_niche, size, align, - repr_align: None, + max_repr_align: None, unadjusted_abi_align: align.abi, }); debug!("generator layout ({:?}): {:#?}", ty, layout); diff --git a/tests/codegen/align-byval.rs b/tests/codegen/align-byval.rs index fc5f795bf67..e2446e02ef4 100644 --- a/tests/codegen/align-byval.rs +++ b/tests/codegen/align-byval.rs @@ -80,7 +80,7 @@ pub struct LowerFA8 { c: i64 } -// On i686-windows, this is passed on stack, because the wrapper struct does not have +// On i686-windows, this is passed by reference, because it contains a field with // requested/forced alignment. #[repr(C)] pub struct WrappedFA8 { @@ -301,7 +301,9 @@ extern "C" { // i686-linux: declare void @wrapped_fa8({{.*}}byval(%WrappedFA8) align 4{{.*}}) - // i686-windows: declare void @wrapped_fa8({{.*}}byval(%WrappedFA8) align 4{{.*}}) + // i686-windows: declare void @wrapped_fa8( + // i686-windows-NOT: byval + // i686-windows-SAME: align 8{{.*}}) fn wrapped_fa8(x: WrappedFA8); // m68k: declare void @transparent_fa8({{.*}}byval(%TransparentFA8) align 8{{.*}}) diff --git a/tests/ui/layout/debug.stderr b/tests/ui/layout/debug.stderr index 1bf89d0dcb3..eeffb3c5f64 100644 --- a/tests/ui/layout/debug.stderr +++ b/tests/ui/layout/debug.stderr @@ -53,7 +53,7 @@ error: layout_of(E) = Layout { variants: Single { index: 0, }, - repr_align: None, + max_repr_align: None, unadjusted_abi_align: Align(1 bytes), }, Layout { @@ -79,12 +79,12 @@ error: layout_of(E) = Layout { variants: Single { index: 1, }, - repr_align: None, + max_repr_align: None, unadjusted_abi_align: Align(4 bytes), }, ], }, - repr_align: None, + max_repr_align: None, unadjusted_abi_align: Align(4 bytes), } --> $DIR/debug.rs:7:1 @@ -130,7 +130,7 @@ error: layout_of(S) = Layout { variants: Single { index: 0, }, - repr_align: None, + max_repr_align: None, unadjusted_abi_align: Align(4 bytes), } --> $DIR/debug.rs:10:1 @@ -154,7 +154,7 @@ error: layout_of(U) = Layout { variants: Single { index: 0, }, - repr_align: None, + max_repr_align: None, unadjusted_abi_align: Align(4 bytes), } --> $DIR/debug.rs:13:1 @@ -247,7 +247,7 @@ error: layout_of(std::result::Result) = Layout { variants: Single { index: 0, }, - repr_align: None, + max_repr_align: None, unadjusted_abi_align: Align(4 bytes), }, Layout { @@ -284,12 +284,12 @@ error: layout_of(std::result::Result) = Layout { variants: Single { index: 1, }, - repr_align: None, + max_repr_align: None, unadjusted_abi_align: Align(4 bytes), }, ], }, - repr_align: None, + max_repr_align: None, unadjusted_abi_align: Align(4 bytes), } --> $DIR/debug.rs:16:1 @@ -317,7 +317,7 @@ error: layout_of(i32) = Layout { variants: Single { index: 0, }, - repr_align: None, + max_repr_align: None, unadjusted_abi_align: Align(4 bytes), } --> $DIR/debug.rs:19:1 @@ -341,7 +341,7 @@ error: layout_of(V) = Layout { variants: Single { index: 0, }, - repr_align: None, + max_repr_align: None, unadjusted_abi_align: Align(2 bytes), } --> $DIR/debug.rs:22:1 @@ -365,7 +365,7 @@ error: layout_of(W) = Layout { variants: Single { index: 0, }, - repr_align: None, + max_repr_align: None, unadjusted_abi_align: Align(2 bytes), } --> $DIR/debug.rs:28:1 @@ -389,7 +389,7 @@ error: layout_of(Y) = Layout { variants: Single { index: 0, }, - repr_align: None, + max_repr_align: None, unadjusted_abi_align: Align(2 bytes), } --> $DIR/debug.rs:34:1 @@ -413,7 +413,7 @@ error: layout_of(P1) = Layout { variants: Single { index: 0, }, - repr_align: None, + max_repr_align: None, unadjusted_abi_align: Align(1 bytes), } --> $DIR/debug.rs:41:1 @@ -437,7 +437,7 @@ error: layout_of(P2) = Layout { variants: Single { index: 0, }, - repr_align: None, + max_repr_align: None, unadjusted_abi_align: Align(1 bytes), } --> $DIR/debug.rs:45:1 @@ -461,7 +461,7 @@ error: layout_of(P3) = Layout { variants: Single { index: 0, }, - repr_align: None, + max_repr_align: None, unadjusted_abi_align: Align(1 bytes), } --> $DIR/debug.rs:53:1 @@ -485,7 +485,7 @@ error: layout_of(P4) = Layout { variants: Single { index: 0, }, - repr_align: None, + max_repr_align: None, unadjusted_abi_align: Align(1 bytes), } --> $DIR/debug.rs:57:1 @@ -514,7 +514,7 @@ error: layout_of(P5) = Layout { variants: Single { index: 0, }, - repr_align: None, + max_repr_align: None, unadjusted_abi_align: Align(1 bytes), } --> $DIR/debug.rs:61:1 @@ -543,7 +543,7 @@ error: layout_of(std::mem::MaybeUninit) = Layout { variants: Single { index: 0, }, - repr_align: None, + max_repr_align: None, unadjusted_abi_align: Align(1 bytes), } --> $DIR/debug.rs:64:1 diff --git a/tests/ui/layout/hexagon-enum.stderr b/tests/ui/layout/hexagon-enum.stderr index acc97672d3c..a2ad4a1ab58 100644 --- a/tests/ui/layout/hexagon-enum.stderr +++ b/tests/ui/layout/hexagon-enum.stderr @@ -59,12 +59,12 @@ error: layout_of(A) = Layout { variants: Single { index: 0, }, - repr_align: None, + max_repr_align: None, unadjusted_abi_align: Align(1 bytes), }, ], }, - repr_align: None, + max_repr_align: None, unadjusted_abi_align: Align(1 bytes), } --> $DIR/hexagon-enum.rs:16:1 @@ -133,12 +133,12 @@ error: layout_of(B) = Layout { variants: Single { index: 0, }, - repr_align: None, + max_repr_align: None, unadjusted_abi_align: Align(1 bytes), }, ], }, - repr_align: None, + max_repr_align: None, unadjusted_abi_align: Align(1 bytes), } --> $DIR/hexagon-enum.rs:20:1 @@ -207,12 +207,12 @@ error: layout_of(C) = Layout { variants: Single { index: 0, }, - repr_align: None, + max_repr_align: None, unadjusted_abi_align: Align(2 bytes), }, ], }, - repr_align: None, + max_repr_align: None, unadjusted_abi_align: Align(2 bytes), } --> $DIR/hexagon-enum.rs:24:1 @@ -281,12 +281,12 @@ error: layout_of(P) = Layout { variants: Single { index: 0, }, - repr_align: None, + max_repr_align: None, unadjusted_abi_align: Align(4 bytes), }, ], }, - repr_align: None, + max_repr_align: None, unadjusted_abi_align: Align(4 bytes), } --> $DIR/hexagon-enum.rs:28:1 @@ -355,12 +355,12 @@ error: layout_of(T) = Layout { variants: Single { index: 0, }, - repr_align: None, + max_repr_align: None, unadjusted_abi_align: Align(4 bytes), }, ], }, - repr_align: None, + max_repr_align: None, unadjusted_abi_align: Align(4 bytes), } --> $DIR/hexagon-enum.rs:34:1 diff --git a/tests/ui/layout/issue-96158-scalarpair-payload-might-be-uninit.stderr b/tests/ui/layout/issue-96158-scalarpair-payload-might-be-uninit.stderr index 6e013af199d..d3ba1a295b1 100644 --- a/tests/ui/layout/issue-96158-scalarpair-payload-might-be-uninit.stderr +++ b/tests/ui/layout/issue-96158-scalarpair-payload-might-be-uninit.stderr @@ -81,7 +81,7 @@ error: layout_of(MissingPayloadField) = Layout { variants: Single { index: 0, }, - repr_align: None, + max_repr_align: None, unadjusted_abi_align: Align(1 bytes), }, Layout { @@ -101,12 +101,12 @@ error: layout_of(MissingPayloadField) = Layout { variants: Single { index: 1, }, - repr_align: None, + max_repr_align: None, unadjusted_abi_align: Align(1 bytes), }, ], }, - repr_align: None, + max_repr_align: None, unadjusted_abi_align: Align(1 bytes), } --> $DIR/issue-96158-scalarpair-payload-might-be-uninit.rs:16:1 @@ -199,7 +199,7 @@ error: layout_of(CommonPayloadField) = Layout { variants: Single { index: 0, }, - repr_align: None, + max_repr_align: None, unadjusted_abi_align: Align(1 bytes), }, Layout { @@ -236,12 +236,12 @@ error: layout_of(CommonPayloadField) = Layout { variants: Single { index: 1, }, - repr_align: None, + max_repr_align: None, unadjusted_abi_align: Align(1 bytes), }, ], }, - repr_align: None, + max_repr_align: None, unadjusted_abi_align: Align(1 bytes), } --> $DIR/issue-96158-scalarpair-payload-might-be-uninit.rs:25:1 @@ -332,7 +332,7 @@ error: layout_of(CommonPayloadFieldIsMaybeUninit) = Layout { variants: Single { index: 0, }, - repr_align: None, + max_repr_align: None, unadjusted_abi_align: Align(1 bytes), }, Layout { @@ -368,12 +368,12 @@ error: layout_of(CommonPayloadFieldIsMaybeUninit) = Layout { variants: Single { index: 1, }, - repr_align: None, + max_repr_align: None, unadjusted_abi_align: Align(1 bytes), }, ], }, - repr_align: None, + max_repr_align: None, unadjusted_abi_align: Align(1 bytes), } --> $DIR/issue-96158-scalarpair-payload-might-be-uninit.rs:33:1 @@ -480,7 +480,7 @@ error: layout_of(NicheFirst) = Layout { variants: Single { index: 0, }, - repr_align: None, + max_repr_align: None, unadjusted_abi_align: Align(1 bytes), }, Layout { @@ -500,7 +500,7 @@ error: layout_of(NicheFirst) = Layout { variants: Single { index: 1, }, - repr_align: None, + max_repr_align: None, unadjusted_abi_align: Align(1 bytes), }, Layout { @@ -520,12 +520,12 @@ error: layout_of(NicheFirst) = Layout { variants: Single { index: 2, }, - repr_align: None, + max_repr_align: None, unadjusted_abi_align: Align(1 bytes), }, ], }, - repr_align: None, + max_repr_align: None, unadjusted_abi_align: Align(1 bytes), } --> $DIR/issue-96158-scalarpair-payload-might-be-uninit.rs:41:1 @@ -632,7 +632,7 @@ error: layout_of(NicheSecond) = Layout { variants: Single { index: 0, }, - repr_align: None, + max_repr_align: None, unadjusted_abi_align: Align(1 bytes), }, Layout { @@ -652,7 +652,7 @@ error: layout_of(NicheSecond) = Layout { variants: Single { index: 1, }, - repr_align: None, + max_repr_align: None, unadjusted_abi_align: Align(1 bytes), }, Layout { @@ -672,12 +672,12 @@ error: layout_of(NicheSecond) = Layout { variants: Single { index: 2, }, - repr_align: None, + max_repr_align: None, unadjusted_abi_align: Align(1 bytes), }, ], }, - repr_align: None, + max_repr_align: None, unadjusted_abi_align: Align(1 bytes), } --> $DIR/issue-96158-scalarpair-payload-might-be-uninit.rs:50:1 diff --git a/tests/ui/layout/issue-96185-overaligned-enum.stderr b/tests/ui/layout/issue-96185-overaligned-enum.stderr index ef6cc79eedb..c539eb453d9 100644 --- a/tests/ui/layout/issue-96185-overaligned-enum.stderr +++ b/tests/ui/layout/issue-96185-overaligned-enum.stderr @@ -53,7 +53,7 @@ error: layout_of(Aligned1) = Layout { variants: Single { index: 0, }, - repr_align: Some( + max_repr_align: Some( Align(8 bytes), ), unadjusted_abi_align: Align(1 bytes), @@ -75,14 +75,14 @@ error: layout_of(Aligned1) = Layout { variants: Single { index: 1, }, - repr_align: Some( + max_repr_align: Some( Align(8 bytes), ), unadjusted_abi_align: Align(1 bytes), }, ], }, - repr_align: Some( + max_repr_align: Some( Align(8 bytes), ), unadjusted_abi_align: Align(1 bytes), @@ -153,7 +153,7 @@ error: layout_of(Aligned2) = Layout { variants: Single { index: 0, }, - repr_align: Some( + max_repr_align: Some( Align(1 bytes), ), unadjusted_abi_align: Align(1 bytes), @@ -175,14 +175,14 @@ error: layout_of(Aligned2) = Layout { variants: Single { index: 1, }, - repr_align: Some( + max_repr_align: Some( Align(1 bytes), ), unadjusted_abi_align: Align(1 bytes), }, ], }, - repr_align: Some( + max_repr_align: Some( Align(1 bytes), ), unadjusted_abi_align: Align(1 bytes), diff --git a/tests/ui/layout/thumb-enum.stderr b/tests/ui/layout/thumb-enum.stderr index c1837b0e47e..6f6ab498206 100644 --- a/tests/ui/layout/thumb-enum.stderr +++ b/tests/ui/layout/thumb-enum.stderr @@ -59,12 +59,12 @@ error: layout_of(A) = Layout { variants: Single { index: 0, }, - repr_align: None, + max_repr_align: None, unadjusted_abi_align: Align(1 bytes), }, ], }, - repr_align: None, + max_repr_align: None, unadjusted_abi_align: Align(1 bytes), } --> $DIR/thumb-enum.rs:16:1 @@ -133,12 +133,12 @@ error: layout_of(B) = Layout { variants: Single { index: 0, }, - repr_align: None, + max_repr_align: None, unadjusted_abi_align: Align(1 bytes), }, ], }, - repr_align: None, + max_repr_align: None, unadjusted_abi_align: Align(1 bytes), } --> $DIR/thumb-enum.rs:20:1 @@ -207,12 +207,12 @@ error: layout_of(C) = Layout { variants: Single { index: 0, }, - repr_align: None, + max_repr_align: None, unadjusted_abi_align: Align(2 bytes), }, ], }, - repr_align: None, + max_repr_align: None, unadjusted_abi_align: Align(2 bytes), } --> $DIR/thumb-enum.rs:24:1 @@ -281,12 +281,12 @@ error: layout_of(P) = Layout { variants: Single { index: 0, }, - repr_align: None, + max_repr_align: None, unadjusted_abi_align: Align(4 bytes), }, ], }, - repr_align: None, + max_repr_align: None, unadjusted_abi_align: Align(4 bytes), } --> $DIR/thumb-enum.rs:28:1 @@ -355,12 +355,12 @@ error: layout_of(T) = Layout { variants: Single { index: 0, }, - repr_align: None, + max_repr_align: None, unadjusted_abi_align: Align(4 bytes), }, ], }, - repr_align: None, + max_repr_align: None, unadjusted_abi_align: Align(4 bytes), } --> $DIR/thumb-enum.rs:34:1 diff --git a/tests/ui/layout/zero-sized-array-enum-niche.stderr b/tests/ui/layout/zero-sized-array-enum-niche.stderr index 02bf9d496bc..df9f1cc8d10 100644 --- a/tests/ui/layout/zero-sized-array-enum-niche.stderr +++ b/tests/ui/layout/zero-sized-array-enum-niche.stderr @@ -57,7 +57,7 @@ error: layout_of(std::result::Result<[u32; 0], bool>) = Layout { variants: Single { index: 0, }, - repr_align: None, + max_repr_align: None, unadjusted_abi_align: Align(4 bytes), }, Layout { @@ -90,12 +90,12 @@ error: layout_of(std::result::Result<[u32; 0], bool>) = Layout { variants: Single { index: 1, }, - repr_align: None, + max_repr_align: None, unadjusted_abi_align: Align(1 bytes), }, ], }, - repr_align: None, + max_repr_align: None, unadjusted_abi_align: Align(4 bytes), } --> $DIR/zero-sized-array-enum-niche.rs:13:1 @@ -162,7 +162,7 @@ error: layout_of(MultipleAlignments) = Layout { variants: Single { index: 0, }, - repr_align: None, + max_repr_align: None, unadjusted_abi_align: Align(2 bytes), }, Layout { @@ -186,7 +186,7 @@ error: layout_of(MultipleAlignments) = Layout { variants: Single { index: 1, }, - repr_align: None, + max_repr_align: None, unadjusted_abi_align: Align(4 bytes), }, Layout { @@ -219,12 +219,12 @@ error: layout_of(MultipleAlignments) = Layout { variants: Single { index: 2, }, - repr_align: None, + max_repr_align: None, unadjusted_abi_align: Align(1 bytes), }, ], }, - repr_align: None, + max_repr_align: None, unadjusted_abi_align: Align(4 bytes), } --> $DIR/zero-sized-array-enum-niche.rs:21:1 @@ -291,7 +291,7 @@ error: layout_of(std::result::Result<[u32; 0], Packed>) = variants: Single { index: 0, }, - repr_align: None, + max_repr_align: None, unadjusted_abi_align: Align(4 bytes), }, Layout { @@ -324,12 +324,12 @@ error: layout_of(std::result::Result<[u32; 0], Packed>) = variants: Single { index: 1, }, - repr_align: None, + max_repr_align: None, unadjusted_abi_align: Align(1 bytes), }, ], }, - repr_align: None, + max_repr_align: None, unadjusted_abi_align: Align(4 bytes), } --> $DIR/zero-sized-array-enum-niche.rs:37:1 @@ -400,7 +400,7 @@ error: layout_of(std::result::Result<[u32; 0], Packed>) = Layout { variants: Single { index: 0, }, - repr_align: None, + max_repr_align: None, unadjusted_abi_align: Align(4 bytes), }, Layout { @@ -433,12 +433,12 @@ error: layout_of(std::result::Result<[u32; 0], Packed>) = Layout { variants: Single { index: 1, }, - repr_align: None, + max_repr_align: None, unadjusted_abi_align: Align(1 bytes), }, ], }, - repr_align: None, + max_repr_align: None, unadjusted_abi_align: Align(4 bytes), } --> $DIR/zero-sized-array-enum-niche.rs:44:1 -- cgit 1.4.1-3-g733a5