Skip to content

Commit 4afd45e

Browse files
committed
Rollup merge of rust-lang#24472 - dotdash:23431, r=nikomatsakis
Loading from and storing to small aggregates happens by casting the aggregate pointer to an appropriately sized integer pointer to avoid the usage of first class aggregates which would lead to less optimized code. But this means that, for example, a tuple of type (i16, i16) will be loading through an i32 pointer and because we currently don't provide alignment information LLVM assumes that the load should use the ABI alignment for i32 which would usually be 4 byte alignment. But the alignment requirement for the (i16, i16) tuple will usually be just 2 bytes, so we're overestimating alignment, which invokes undefined behaviour. Therefore we must emit appropriate alignment information for stores/loads through such casted pointers. Fixes rust-lang#23431
2 parents 514e06d + 78745a4 commit 4afd45e

File tree

6 files changed

+42
-16
lines changed

6 files changed

+42
-16
lines changed

src/librustc_trans/trans/adt.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -880,7 +880,7 @@ pub fn trans_set_discr<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, r: &Repr<'tcx>,
880880
CEnum(ity, min, max) => {
881881
assert_discr_in_range(ity, min, max, discr);
882882
Store(bcx, C_integral(ll_inttype(bcx.ccx(), ity), discr as u64, true),
883-
val)
883+
val);
884884
}
885885
General(ity, ref cases, dtor) => {
886886
if dtor_active(dtor) {
@@ -889,7 +889,7 @@ pub fn trans_set_discr<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, r: &Repr<'tcx>,
889889
Store(bcx, C_u8(bcx.ccx(), DTOR_NEEDED as usize), ptr);
890890
}
891891
Store(bcx, C_integral(ll_inttype(bcx.ccx(), ity), discr as u64, true),
892-
GEPi(bcx, val, &[0, 0]))
892+
GEPi(bcx, val, &[0, 0]));
893893
}
894894
Univariant(ref st, dtor) => {
895895
assert_eq!(discr, 0);
@@ -901,14 +901,14 @@ pub fn trans_set_discr<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, r: &Repr<'tcx>,
901901
RawNullablePointer { nndiscr, nnty, ..} => {
902902
if discr != nndiscr {
903903
let llptrty = type_of::sizing_type_of(bcx.ccx(), nnty);
904-
Store(bcx, C_null(llptrty), val)
904+
Store(bcx, C_null(llptrty), val);
905905
}
906906
}
907907
StructWrappedNullablePointer { nndiscr, ref discrfield, .. } => {
908908
if discr != nndiscr {
909909
let llptrptr = GEPi(bcx, val, &discrfield[..]);
910910
let llptrty = val_ty(llptrptr).element_type();
911-
Store(bcx, C_null(llptrty), llptrptr)
911+
Store(bcx, C_null(llptrty), llptrptr);
912912
}
913913
}
914914
}

src/librustc_trans/trans/base.rs

+18-2
Original file line numberDiff line numberDiff line change
@@ -765,9 +765,14 @@ pub fn load_ty<'blk, 'tcx>(cx: Block<'blk, 'tcx>,
765765
}
766766

767767
let ptr = to_arg_ty_ptr(cx, ptr, t);
768+
let align = type_of::align_of(cx.ccx(), t);
768769

769770
if type_is_immediate(cx.ccx(), t) && type_of::type_of(cx.ccx(), t).is_aggregate() {
770-
return Load(cx, ptr);
771+
let load = Load(cx, ptr);
772+
unsafe {
773+
llvm::LLVMSetAlignment(load, align);
774+
}
775+
return load;
771776
}
772777

773778
unsafe {
@@ -793,13 +798,24 @@ pub fn load_ty<'blk, 'tcx>(cx: Block<'blk, 'tcx>,
793798
Load(cx, ptr)
794799
};
795800

801+
unsafe {
802+
llvm::LLVMSetAlignment(val, align);
803+
}
804+
796805
from_arg_ty(cx, val, t)
797806
}
798807

799808
/// Helper for storing values in memory. Does the necessary conversion if the in-memory type
800809
/// differs from the type used for SSA values.
801810
pub fn store_ty<'blk, 'tcx>(cx: Block<'blk, 'tcx>, v: ValueRef, dst: ValueRef, t: Ty<'tcx>) {
802-
Store(cx, to_arg_ty(cx, v, t), to_arg_ty_ptr(cx, dst, t));
811+
if cx.unreachable.get() {
812+
return;
813+
}
814+
815+
let store = Store(cx, to_arg_ty(cx, v, t), to_arg_ty_ptr(cx, dst, t));
816+
unsafe {
817+
llvm::LLVMSetAlignment(store, type_of::align_of(cx.ccx(), t));
818+
}
803819
}
804820

805821
pub fn to_arg_ty(bcx: Block, val: ValueRef, ty: Ty) -> ValueRef {

src/librustc_trans/trans/build.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -646,13 +646,13 @@ pub fn LoadNonNull(cx: Block, ptr: ValueRef) -> ValueRef {
646646
}
647647
}
648648

649-
pub fn Store(cx: Block, val: ValueRef, ptr: ValueRef) {
650-
if cx.unreachable.get() { return; }
649+
pub fn Store(cx: Block, val: ValueRef, ptr: ValueRef) -> ValueRef {
650+
if cx.unreachable.get() { return C_nil(cx.ccx()); }
651651
B(cx).store(val, ptr)
652652
}
653653

654-
pub fn VolatileStore(cx: Block, val: ValueRef, ptr: ValueRef) {
655-
if cx.unreachable.get() { return; }
654+
pub fn VolatileStore(cx: Block, val: ValueRef, ptr: ValueRef) -> ValueRef {
655+
if cx.unreachable.get() { return C_nil(cx.ccx()); }
656656
B(cx).volatile_store(val, ptr)
657657
}
658658

src/librustc_trans/trans/builder.rs

+4-3
Original file line numberDiff line numberDiff line change
@@ -509,18 +509,18 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
509509
value
510510
}
511511

512-
pub fn store(&self, val: ValueRef, ptr: ValueRef) {
512+
pub fn store(&self, val: ValueRef, ptr: ValueRef) -> ValueRef {
513513
debug!("Store {} -> {}",
514514
self.ccx.tn().val_to_string(val),
515515
self.ccx.tn().val_to_string(ptr));
516516
assert!(!self.llbuilder.is_null());
517517
self.count_insn("store");
518518
unsafe {
519-
llvm::LLVMBuildStore(self.llbuilder, val, ptr);
519+
llvm::LLVMBuildStore(self.llbuilder, val, ptr)
520520
}
521521
}
522522

523-
pub fn volatile_store(&self, val: ValueRef, ptr: ValueRef) {
523+
pub fn volatile_store(&self, val: ValueRef, ptr: ValueRef) -> ValueRef {
524524
debug!("Store {} -> {}",
525525
self.ccx.tn().val_to_string(val),
526526
self.ccx.tn().val_to_string(ptr));
@@ -529,6 +529,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
529529
unsafe {
530530
let insn = llvm::LLVMBuildStore(self.llbuilder, val, ptr);
531531
llvm::LLVMSetVolatile(insn, llvm::True);
532+
insn
532533
}
533534
}
534535

src/librustc_trans/trans/foreign.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -802,7 +802,9 @@ pub fn trans_rust_fn_with_foreign_abi<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
802802
// appropriately sized integer and we have to convert it
803803
let tmp = builder.bitcast(llforeign_arg,
804804
type_of::arg_type_of(ccx, rust_ty).ptr_to());
805-
builder.load(tmp)
805+
let load = builder.load(tmp);
806+
llvm::LLVMSetAlignment(load, type_of::align_of(ccx, rust_ty));
807+
load
806808
} else {
807809
builder.load(llforeign_arg)
808810
}

src/librustc_trans/trans/intrinsic.rs

+9-2
Original file line numberDiff line numberDiff line change
@@ -456,13 +456,20 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
456456
(_, "volatile_load") => {
457457
let tp_ty = *substs.types.get(FnSpace, 0);
458458
let ptr = to_arg_ty_ptr(bcx, llargs[0], tp_ty);
459-
from_arg_ty(bcx, VolatileLoad(bcx, ptr), tp_ty)
459+
let load = VolatileLoad(bcx, ptr);
460+
unsafe {
461+
llvm::LLVMSetAlignment(load, type_of::align_of(ccx, tp_ty));
462+
}
463+
from_arg_ty(bcx, load, tp_ty)
460464
},
461465
(_, "volatile_store") => {
462466
let tp_ty = *substs.types.get(FnSpace, 0);
463467
let ptr = to_arg_ty_ptr(bcx, llargs[0], tp_ty);
464468
let val = to_arg_ty(bcx, llargs[1], tp_ty);
465-
VolatileStore(bcx, val, ptr);
469+
let store = VolatileStore(bcx, val, ptr);
470+
unsafe {
471+
llvm::LLVMSetAlignment(store, type_of::align_of(ccx, tp_ty));
472+
}
466473
C_nil(ccx)
467474
},
468475

0 commit comments

Comments
 (0)