Skip to content

Commit 841af07

Browse files
authored
Rollup merge of rust-lang#57053 - nikic:fix-gep-align, r=nagisa
Fix alignment for array indexing We need to reduce the alignment with the used offset. If the offset isn't known, use the element size, as this will yield the minimum possible alignment. This handles both direct array indexing, and array repeat expressions. Fixes rust-lang#56927. r? @nagisa
2 parents ee1c818 + 097d39d commit 841af07

File tree

4 files changed

+93
-3
lines changed

4 files changed

+93
-3
lines changed

src/librustc_codegen_ssa/mir/place.rs

+11-2
Original file line numberDiff line numberDiff line change
@@ -335,11 +335,20 @@ impl<'a, 'tcx: 'a, V: CodegenObject> PlaceRef<'tcx, V> {
335335
bx: &mut Bx,
336336
llindex: V
337337
) -> Self {
338+
// Statically compute the offset if we can, otherwise just use the element size,
339+
// as this will yield the lowest alignment.
340+
let layout = self.layout.field(bx, 0);
341+
let offset = if bx.is_const_integral(llindex) {
342+
layout.size.checked_mul(bx.const_to_uint(llindex), bx).unwrap_or(layout.size)
343+
} else {
344+
layout.size
345+
};
346+
338347
PlaceRef {
339348
llval: bx.inbounds_gep(self.llval, &[bx.cx().const_usize(0), llindex]),
340349
llextra: None,
341-
layout: self.layout.field(bx.cx(), 0),
342-
align: self.align
350+
layout,
351+
align: self.align.restrict_for_offset(offset),
343352
}
344353
}
345354

src/librustc_codegen_ssa/mir/rvalue.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -131,8 +131,9 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
131131
let keep_going = header_bx.icmp(IntPredicate::IntNE, current, end);
132132
header_bx.cond_br(keep_going, body_bx.llbb(), next_bx.llbb());
133133

134+
let align = dest.align.restrict_for_offset(dest.layout.field(bx.cx(), 0).size);
134135
cg_elem.val.store(&mut body_bx,
135-
PlaceRef::new_sized(current, cg_elem.layout, dest.align));
136+
PlaceRef::new_sized(current, cg_elem.layout, align));
136137

137138
let next = body_bx.inbounds_gep(current, &[bx.cx().const_usize(1)]);
138139
body_bx.br(header_bx.llbb());

src/test/codegen/issue-56927.rs

+44
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
// compile-flags: -C no-prepopulate-passes
2+
3+
#![crate_type="rlib"]
4+
use std::usize;
5+
6+
#[repr(align(16))]
7+
pub struct S {
8+
arr: [u32; 4],
9+
}
10+
11+
// CHECK-LABEL: @test1
12+
// CHECK: store i32 0, i32* %{{.+}}, align 16
13+
// CHECK: store i32 1, i32* %{{.+}}, align 4
14+
// CHECK: store i32 2, i32* %{{.+}}, align 8
15+
// CHECK: store i32 3, i32* %{{.+}}, align 4
16+
#[no_mangle]
17+
pub fn test1(s: &mut S) {
18+
s.arr[0] = 0;
19+
s.arr[1] = 1;
20+
s.arr[2] = 2;
21+
s.arr[3] = 3;
22+
}
23+
24+
// CHECK-LABEL: @test2
25+
// CHECK: store i32 4, i32* %{{.+}}, align 4
26+
#[allow(const_err)]
27+
#[no_mangle]
28+
pub fn test2(s: &mut S) {
29+
s.arr[usize::MAX / 4 + 1] = 4;
30+
}
31+
32+
// CHECK-LABEL: @test3
33+
// CHECK: store i32 5, i32* %{{.+}}, align 4
34+
#[no_mangle]
35+
pub fn test3(s: &mut S, i: usize) {
36+
s.arr[i] = 5;
37+
}
38+
39+
// CHECK-LABEL: @test4
40+
// CHECK: store i32 6, i32* %{{.+}}, align 4
41+
#[no_mangle]
42+
pub fn test4(s: &mut S) {
43+
s.arr = [6; 4];
44+
}

src/test/codegen/packed.rs

+36
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,42 @@ pub fn call_pkd2(f: fn() -> Array) -> BigPacked2 {
8383
BigPacked2 { dealign: 0, data: f() }
8484
}
8585

86+
// CHECK-LABEL: @write_packed_array1
87+
// CHECK: store i32 0, i32* %{{.+}}, align 1
88+
// CHECK: store i32 1, i32* %{{.+}}, align 1
89+
// CHECK: store i32 2, i32* %{{.+}}, align 1
90+
#[no_mangle]
91+
pub fn write_packed_array1(p: &mut BigPacked1) {
92+
p.data.0[0] = 0;
93+
p.data.0[1] = 1;
94+
p.data.0[2] = 2;
95+
}
96+
97+
// CHECK-LABEL: @write_packed_array2
98+
// CHECK: store i32 0, i32* %{{.+}}, align 2
99+
// CHECK: store i32 1, i32* %{{.+}}, align 2
100+
// CHECK: store i32 2, i32* %{{.+}}, align 2
101+
#[no_mangle]
102+
pub fn write_packed_array2(p: &mut BigPacked2) {
103+
p.data.0[0] = 0;
104+
p.data.0[1] = 1;
105+
p.data.0[2] = 2;
106+
}
107+
108+
// CHECK-LABEL: @repeat_packed_array1
109+
// CHECK: store i32 42, i32* %{{.+}}, align 1
110+
#[no_mangle]
111+
pub fn repeat_packed_array1(p: &mut BigPacked1) {
112+
p.data.0 = [42; 8];
113+
}
114+
115+
// CHECK-LABEL: @repeat_packed_array2
116+
// CHECK: store i32 42, i32* %{{.+}}, align 2
117+
#[no_mangle]
118+
pub fn repeat_packed_array2(p: &mut BigPacked2) {
119+
p.data.0 = [42; 8];
120+
}
121+
86122
#[repr(packed)]
87123
#[derive(Copy, Clone)]
88124
pub struct Packed1Pair(u8, u32);

0 commit comments

Comments
 (0)