Skip to content

Commit

Permalink
Rollup merge of rust-lang#40385 - arielb1:packed-again, r=eddyb
Browse files Browse the repository at this point in the history
emit !align attributes on stores of operand pairs

This avoids another case of missing-align UB. cc rust-lang#40373

r? @eddyb
  • Loading branch information
Ariel Ben-Yehuda authored and alexcrichton committed Mar 10, 2017
2 parents 0c8f19a + 14e9313 commit f2e0220
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 4 deletions.
17 changes: 15 additions & 2 deletions src/librustc_trans/mir/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -833,8 +833,21 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
self.trans_lvalue(bcx, dest)
};
if fn_ret_ty.is_indirect() {
llargs.push(dest.llval);
ReturnDest::Nothing
match dest.alignment {
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 {
ReturnDest::Store(dest.llval)
}
Expand Down
11 changes: 9 additions & 2 deletions src/librustc_trans/mir/operand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -268,10 +268,17 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
bcx.store(base::from_immediate(bcx, s), lldest, align);
}
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 b = base::from_immediate(bcx, b);
bcx.store(a, bcx.struct_gep(lldest, 0), align);
bcx.store(b, bcx.struct_gep(lldest, 1), align);
bcx.store(a, bcx.struct_gep(lldest, 0), f_align);
bcx.store(b, bcx.struct_gep(lldest, 1), f_align);
}
}
}
Expand Down
33 changes: 33 additions & 0 deletions src/test/codegen/packed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,36 @@ pub fn write_pkd(pkd: &mut Packed) -> u32 {
pkd.data = 42;
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.p0i8.p0i8.i64(i8* %{{.*}}, i8* %{{.*}}, i64 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;
}

0 comments on commit f2e0220

Please sign in to comment.