mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-25 08:13:41 +00:00
Auto merge of #40385 - arielb1:packed-again, r=eddyb
emit !align attributes on stores of operand pairs This avoids another case of missing-align UB. cc #40373 r? @eddyb
This commit is contained in:
commit
ddc1708b73
@ -833,8 +833,21 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
|
|||||||
self.trans_lvalue(bcx, dest)
|
self.trans_lvalue(bcx, dest)
|
||||||
};
|
};
|
||||||
if fn_ret_ty.is_indirect() {
|
if fn_ret_ty.is_indirect() {
|
||||||
llargs.push(dest.llval);
|
match dest.alignment {
|
||||||
ReturnDest::Nothing
|
Alignment::AbiAligned => {
|
||||||
|
llargs.push(dest.llval);
|
||||||
|
ReturnDest::Nothing
|
||||||
|
},
|
||||||
|
Alignment::Packed => {
|
||||||
|
// Currently, MIR code generation does not create calls
|
||||||
|
// that store directly to fields of packed structs (in
|
||||||
|
// fact, the calls it creates write only to temps),
|
||||||
|
//
|
||||||
|
// If someone changes that, please update this code path
|
||||||
|
// to create a temporary.
|
||||||
|
span_bug!(self.mir.span, "can't directly store to unaligned value");
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
ReturnDest::Store(dest.llval)
|
ReturnDest::Store(dest.llval)
|
||||||
}
|
}
|
||||||
|
@ -268,10 +268,17 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
|
|||||||
bcx.store(base::from_immediate(bcx, s), lldest, align);
|
bcx.store(base::from_immediate(bcx, s), lldest, align);
|
||||||
}
|
}
|
||||||
OperandValue::Pair(a, b) => {
|
OperandValue::Pair(a, b) => {
|
||||||
|
let f_align = match *bcx.ccx.layout_of(operand.ty) {
|
||||||
|
Layout::Univariant { ref variant, .. } if variant.packed => {
|
||||||
|
Some(1)
|
||||||
|
}
|
||||||
|
_ => align
|
||||||
|
};
|
||||||
|
|
||||||
let a = base::from_immediate(bcx, a);
|
let a = base::from_immediate(bcx, a);
|
||||||
let b = base::from_immediate(bcx, b);
|
let b = base::from_immediate(bcx, b);
|
||||||
bcx.store(a, bcx.struct_gep(lldest, 0), align);
|
bcx.store(a, bcx.struct_gep(lldest, 0), f_align);
|
||||||
bcx.store(b, bcx.struct_gep(lldest, 1), align);
|
bcx.store(b, bcx.struct_gep(lldest, 1), f_align);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -27,3 +27,36 @@ pub fn write_pkd(pkd: &mut Packed) -> u32 {
|
|||||||
pkd.data = 42;
|
pkd.data = 42;
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct Array([i32; 8]);
|
||||||
|
#[repr(packed)]
|
||||||
|
pub struct BigPacked {
|
||||||
|
dealign: u8,
|
||||||
|
data: Array
|
||||||
|
}
|
||||||
|
|
||||||
|
// CHECK-LABEL: @call_pkd
|
||||||
|
#[no_mangle]
|
||||||
|
pub fn call_pkd(f: fn() -> Array) -> BigPacked {
|
||||||
|
// CHECK: [[ALLOCA:%[_a-z0-9]+]] = alloca %Array
|
||||||
|
// CHECK: call void %{{.*}}(%Array* noalias nocapture sret dereferenceable(32) [[ALLOCA]])
|
||||||
|
// CHECK: call void @llvm.memcpy.{{.*}}(i8* %{{.*}}, i8* %{{.*}}, i{{[0-9]+}} 32, i32 1, i1 false)
|
||||||
|
// check that calls whose destination is a field of a packed struct
|
||||||
|
// go through an alloca rather than calling the function with an
|
||||||
|
// unaligned destination.
|
||||||
|
BigPacked { dealign: 0, data: f() }
|
||||||
|
}
|
||||||
|
|
||||||
|
#[repr(packed)]
|
||||||
|
#[derive(Copy, Clone)]
|
||||||
|
pub struct PackedPair(u8, u32);
|
||||||
|
|
||||||
|
// CHECK-LABEL: @pkd_pair
|
||||||
|
#[no_mangle]
|
||||||
|
pub fn pkd_pair(pair1: &mut PackedPair, pair2: &mut PackedPair) {
|
||||||
|
// CHECK: [[V1:%[a-z0-9]+]] = load i8, i8* %{{.*}}, align 1
|
||||||
|
// CHECK: [[V2:%[a-z0-9]+]] = load i32, i32* %{{.*}}, align 1
|
||||||
|
// CHECK: store i8 [[V1]], i8* {{.*}}, align 1
|
||||||
|
// CHECK: store i32 [[V2]], i32* {{.*}}, align 1
|
||||||
|
*pair2 = *pair1;
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user