Skip to content

Commit 097d39d

Browse files
committed
Fix alignment for array indexing
We need to reduce the alignment with the used offset. If the offset isn't known, we need to reduce with the element size to support arbitrary offsets.
1 parent 6d34ec1 commit 097d39d

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
@@ -84,6 +84,42 @@ pub fn call_pkd2(f: fn() -> Array) -> BigPacked2 {
8484
BigPacked2 { dealign: 0, data: f() }
8585
}
8686

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

0 commit comments

Comments
 (0)