Skip to content

Commit 524ad2a

Browse files
author
Ariel Ben-Yehuda
authored
Rollup merge of rust-lang#40385 - arielb1:packed-again, r=eddyb
emit !align attributes on stores of operand pairs This avoids another case of missing-align UB. cc rust-lang#40373 r? @eddyb
2 parents 3a7f3d2 + 038ec50 commit 524ad2a

File tree

3 files changed

+57
-4
lines changed

3 files changed

+57
-4
lines changed

src/librustc_trans/mir/block.rs

+15-2
Original file line numberDiff line numberDiff line change
@@ -833,8 +833,21 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
833833
self.trans_lvalue(bcx, dest)
834834
};
835835
if fn_ret_ty.is_indirect() {
836-
llargs.push(dest.llval);
837-
ReturnDest::Nothing
836+
match dest.alignment {
837+
Alignment::AbiAligned => {
838+
llargs.push(dest.llval);
839+
ReturnDest::Nothing
840+
},
841+
Alignment::Packed => {
842+
// Currently, MIR code generation does not create calls
843+
// that store directly to fields of packed structs (in
844+
// fact, the calls it creates write only to temps),
845+
//
846+
// If someone changes that, please update this code path
847+
// to create a temporary.
848+
span_bug!(self.mir.span, "can't directly store to unaligned value");
849+
}
850+
}
838851
} else {
839852
ReturnDest::Store(dest.llval)
840853
}

src/librustc_trans/mir/operand.rs

+9-2
Original file line numberDiff line numberDiff line change
@@ -268,10 +268,17 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
268268
bcx.store(base::from_immediate(bcx, s), lldest, align);
269269
}
270270
OperandValue::Pair(a, b) => {
271+
let f_align = match *bcx.ccx.layout_of(operand.ty) {
272+
Layout::Univariant { ref variant, .. } if variant.packed => {
273+
Some(1)
274+
}
275+
_ => align
276+
};
277+
271278
let a = base::from_immediate(bcx, a);
272279
let b = base::from_immediate(bcx, b);
273-
bcx.store(a, bcx.struct_gep(lldest, 0), align);
274-
bcx.store(b, bcx.struct_gep(lldest, 1), align);
280+
bcx.store(a, bcx.struct_gep(lldest, 0), f_align);
281+
bcx.store(b, bcx.struct_gep(lldest, 1), f_align);
275282
}
276283
}
277284
}

src/test/codegen/packed.rs

+33
Original file line numberDiff line numberDiff line change
@@ -27,3 +27,36 @@ pub fn write_pkd(pkd: &mut Packed) -> u32 {
2727
pkd.data = 42;
2828
result
2929
}
30+
31+
pub struct Array([i32; 8]);
32+
#[repr(packed)]
33+
pub struct BigPacked {
34+
dealign: u8,
35+
data: Array
36+
}
37+
38+
// CHECK-LABEL: @call_pkd
39+
#[no_mangle]
40+
pub fn call_pkd(f: fn() -> Array) -> BigPacked {
41+
// CHECK: [[ALLOCA:%[_a-z0-9]+]] = alloca %Array
42+
// CHECK: call void %{{.*}}(%Array* noalias nocapture sret dereferenceable(32) [[ALLOCA]])
43+
// CHECK: call void @llvm.memcpy.{{.*}}(i8* %{{.*}}, i8* %{{.*}}, i{{[0-9]+}} 32, i32 1, i1 false)
44+
// check that calls whose destination is a field of a packed struct
45+
// go through an alloca rather than calling the function with an
46+
// unaligned destination.
47+
BigPacked { dealign: 0, data: f() }
48+
}
49+
50+
#[repr(packed)]
51+
#[derive(Copy, Clone)]
52+
pub struct PackedPair(u8, u32);
53+
54+
// CHECK-LABEL: @pkd_pair
55+
#[no_mangle]
56+
pub fn pkd_pair(pair1: &mut PackedPair, pair2: &mut PackedPair) {
57+
// CHECK: [[V1:%[a-z0-9]+]] = load i8, i8* %{{.*}}, align 1
58+
// CHECK: [[V2:%[a-z0-9]+]] = load i32, i32* %{{.*}}, align 1
59+
// CHECK: store i8 [[V1]], i8* {{.*}}, align 1
60+
// CHECK: store i32 [[V2]], i32* {{.*}}, align 1
61+
*pair2 = *pair1;
62+
}

0 commit comments

Comments
 (0)