Skip to content

Commit d40d01b

Browse files
committed
Auto merge of #38670 - dotdash:transmute_align, r=eddyb
Fix transmute::<T, U> where T requires a bigger alignment than U For transmute::<T, U> we simply pointercast the destination from a U pointer to a T pointer, without providing any alignment information, thus LLVM assumes that the destination is aligned to hold a value of type T, which is not necessarily true. This can lead to LLVM emitting machine instructions that assume said alignment, and thus cause aborts. To fix this, we need to provide the actual alignment to store_operand() and in turn to store() so they can set the proper alignment information on the stores and LLVM can emit the proper machine instructions. Fixes #32947
2 parents 9c0e373 + 71a11a0 commit d40d01b

File tree

11 files changed

+97
-65
lines changed

11 files changed

+97
-65
lines changed

src/librustc_trans/abi.rs

+3-6
Original file line numberDiff line numberDiff line change
@@ -251,11 +251,8 @@ impl ArgType {
251251
let can_store_through_cast_ptr = false;
252252
if can_store_through_cast_ptr {
253253
let cast_dst = bcx.pointercast(dst, ty.ptr_to());
254-
let store = bcx.store(val, cast_dst);
255254
let llalign = llalign_of_min(ccx, self.ty);
256-
unsafe {
257-
llvm::LLVMSetAlignment(store, llalign);
258-
}
255+
bcx.store(val, cast_dst, Some(llalign));
259256
} else {
260257
// The actual return type is a struct, but the ABI
261258
// adaptation code has cast it into some scalar type. The
@@ -276,7 +273,7 @@ impl ArgType {
276273
base::Lifetime::Start.call(bcx, llscratch);
277274

278275
// ...where we first store the value...
279-
bcx.store(val, llscratch);
276+
bcx.store(val, llscratch, None);
280277

281278
// ...and then memcpy it to the intended destination.
282279
base::call_memcpy(bcx,
@@ -292,7 +289,7 @@ impl ArgType {
292289
if self.original_ty == Type::i1(ccx) {
293290
val = bcx.zext(val, Type::i8(ccx));
294291
}
295-
bcx.store(val, dst);
292+
bcx.store(val, dst, None);
296293
}
297294
}
298295

src/librustc_trans/adt.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -443,11 +443,11 @@ pub fn trans_set_discr<'a, 'tcx>(
443443
layout::CEnum{ discr, min, max, .. } => {
444444
assert_discr_in_range(Disr(min), Disr(max), to);
445445
bcx.store(C_integral(Type::from_integer(bcx.ccx, discr), to.0, true),
446-
val);
446+
val, None);
447447
}
448448
layout::General{ discr, .. } => {
449449
bcx.store(C_integral(Type::from_integer(bcx.ccx, discr), to.0, true),
450-
bcx.struct_gep(val, 0));
450+
bcx.struct_gep(val, 0), None);
451451
}
452452
layout::Univariant { .. }
453453
| layout::UntaggedUnion { .. }
@@ -458,7 +458,7 @@ pub fn trans_set_discr<'a, 'tcx>(
458458
let nnty = compute_fields(bcx.ccx, t, nndiscr as usize, false)[0];
459459
if to.0 != nndiscr {
460460
let llptrty = type_of::sizing_type_of(bcx.ccx, nnty);
461-
bcx.store(C_null(llptrty), val);
461+
bcx.store(C_null(llptrty), val, None);
462462
}
463463
}
464464
layout::StructWrappedNullablePointer { nndiscr, ref discrfield, ref nonnull, .. } => {
@@ -476,7 +476,7 @@ pub fn trans_set_discr<'a, 'tcx>(
476476
let path = discrfield.iter().map(|&i| i as usize).collect::<Vec<_>>();
477477
let llptrptr = bcx.gepi(val, &path[..]);
478478
let llptrty = val_ty(llptrptr).element_type();
479-
bcx.store(C_null(llptrty), llptrptr);
479+
bcx.store(C_null(llptrty), llptrptr, None);
480480
}
481481
}
482482
}

src/librustc_trans/asm.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ pub fn trans_inline_asm<'a, 'tcx>(
105105
let outputs = ia.outputs.iter().zip(&outputs).filter(|&(ref o, _)| !o.is_indirect);
106106
for (i, (_, &(val, _))) in outputs.enumerate() {
107107
let v = if num_outputs == 1 { r } else { bcx.extract_value(r, i) };
108-
bcx.store(v, val);
108+
bcx.store(v, val, None);
109109
}
110110

111111
// Store expn_id in a metadata node so we can map LLVM errors

src/librustc_trans/base.rs

+13-18
Original file line numberDiff line numberDiff line change
@@ -290,7 +290,7 @@ pub fn coerce_unsized_into<'a, 'tcx>(bcx: &BlockAndBuilder<'a, 'tcx>,
290290
let src_f = adt::trans_field_ptr(bcx, src_ty, src, Disr(0), i);
291291
let dst_f = adt::trans_field_ptr(bcx, dst_ty, dst, Disr(0), i);
292292
if src_fty == dst_fty {
293-
memcpy_ty(bcx, dst_f, src_f, src_fty);
293+
memcpy_ty(bcx, dst_f, src_f, src_fty, None);
294294
} else {
295295
coerce_unsized_into(bcx, src_f, src_fty, dst_f, dst_fty);
296296
}
@@ -429,7 +429,7 @@ pub fn store_ty<'a, 'tcx>(cx: &BlockAndBuilder<'a, 'tcx>, v: ValueRef, dst: Valu
429429
let llextra = cx.extract_value(v, abi::FAT_PTR_EXTRA);
430430
store_fat_ptr(cx, lladdr, llextra, dst, t);
431431
} else {
432-
cx.store(from_immediate(cx, v), dst);
432+
cx.store(from_immediate(cx, v), dst, None);
433433
}
434434
}
435435

@@ -439,8 +439,8 @@ pub fn store_fat_ptr<'a, 'tcx>(cx: &BlockAndBuilder<'a, 'tcx>,
439439
dst: ValueRef,
440440
_ty: Ty<'tcx>) {
441441
// FIXME: emit metadata
442-
cx.store(data, get_dataptr(cx, dst));
443-
cx.store(extra, get_meta(cx, dst));
442+
cx.store(data, get_dataptr(cx, dst), None);
443+
cx.store(extra, get_meta(cx, dst), None);
444444
}
445445

446446
pub fn load_fat_ptr<'a, 'tcx>(
@@ -523,26 +523,21 @@ pub fn call_memcpy<'a, 'tcx>(b: &Builder<'a, 'tcx>,
523523
b.call(memcpy, &[dst_ptr, src_ptr, size, align, volatile], None);
524524
}
525525

526-
pub fn memcpy_ty<'a, 'tcx>(
527-
bcx: &BlockAndBuilder<'a, 'tcx>, dst: ValueRef, src: ValueRef, t: Ty<'tcx>
528-
) {
526+
pub fn memcpy_ty<'a, 'tcx>(bcx: &BlockAndBuilder<'a, 'tcx>,
527+
dst: ValueRef,
528+
src: ValueRef,
529+
t: Ty<'tcx>,
530+
align: Option<u32>) {
529531
let ccx = bcx.ccx;
530532

531533
if type_is_zero_size(ccx, t) {
532534
return;
533535
}
534536

535-
if t.is_structural() {
536-
let llty = type_of::type_of(ccx, t);
537-
let llsz = llsize_of(ccx, llty);
538-
let llalign = type_of::align_of(ccx, t);
539-
call_memcpy(bcx, dst, src, llsz, llalign as u32);
540-
} else if common::type_is_fat_ptr(bcx.ccx, t) {
541-
let (data, extra) = load_fat_ptr(bcx, src, t);
542-
store_fat_ptr(bcx, data, extra, dst, t);
543-
} else {
544-
store_ty(bcx, load_ty(bcx, src, t), dst, t);
545-
}
537+
let llty = type_of::type_of(ccx, t);
538+
let llsz = llsize_of(ccx, llty);
539+
let llalign = align.unwrap_or_else(|| type_of::align_of(ccx, t));
540+
call_memcpy(bcx, dst, src, llsz, llalign as u32);
546541
}
547542

548543
pub fn call_memset<'a, 'tcx>(b: &Builder<'a, 'tcx>,

src/librustc_trans/builder.rs

+6-2
Original file line numberDiff line numberDiff line change
@@ -512,13 +512,17 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
512512
value
513513
}
514514

515-
pub fn store(&self, val: ValueRef, ptr: ValueRef) -> ValueRef {
515+
pub fn store(&self, val: ValueRef, ptr: ValueRef, align: Option<u32>) -> ValueRef {
516516
debug!("Store {:?} -> {:?}", Value(val), Value(ptr));
517517
assert!(!self.llbuilder.is_null());
518518
self.count_insn("store");
519519
let ptr = self.check_store(val, ptr);
520520
unsafe {
521-
llvm::LLVMBuildStore(self.llbuilder, val, ptr)
521+
let store = llvm::LLVMBuildStore(self.llbuilder, val, ptr);
522+
if let Some(align) = align {
523+
llvm::LLVMSetAlignment(store, align as c_uint);
524+
}
525+
store
522526
}
523527
}
524528

src/librustc_trans/intrinsic.rs

+12-15
Original file line numberDiff line numberDiff line change
@@ -290,8 +290,8 @@ pub fn trans_intrinsic_call<'a, 'tcx>(bcx: &BlockAndBuilder<'a, 'tcx>,
290290
let val = bcx.call(llfn, &[llargs[0], llargs[1]], None);
291291
let result = bcx.extract_value(val, 0);
292292
let overflow = bcx.zext(bcx.extract_value(val, 1), Type::bool(ccx));
293-
bcx.store(result, bcx.struct_gep(llresult, 0));
294-
bcx.store(overflow, bcx.struct_gep(llresult, 1));
293+
bcx.store(result, bcx.struct_gep(llresult, 0), None);
294+
bcx.store(overflow, bcx.struct_gep(llresult, 1), None);
295295

296296
C_nil(bcx.ccx)
297297
},
@@ -409,8 +409,8 @@ pub fn trans_intrinsic_call<'a, 'tcx>(bcx: &BlockAndBuilder<'a, 'tcx>,
409409
failorder, weak);
410410
let result = bcx.extract_value(val, 0);
411411
let success = bcx.zext(bcx.extract_value(val, 1), Type::bool(bcx.ccx));
412-
bcx.store(result, bcx.struct_gep(llresult, 0));
413-
bcx.store(success, bcx.struct_gep(llresult, 1));
412+
bcx.store(result, bcx.struct_gep(llresult, 0), None);
413+
bcx.store(success, bcx.struct_gep(llresult, 1), None);
414414
} else {
415415
invalid_monomorphization(sty);
416416
}
@@ -615,7 +615,7 @@ pub fn trans_intrinsic_call<'a, 'tcx>(bcx: &BlockAndBuilder<'a, 'tcx>,
615615

616616
for i in 0..elems.len() {
617617
let val = bcx.extract_value(val, i);
618-
bcx.store(val, bcx.struct_gep(llresult, i));
618+
bcx.store(val, bcx.struct_gep(llresult, i), None);
619619
}
620620
C_nil(ccx)
621621
}
@@ -627,10 +627,7 @@ pub fn trans_intrinsic_call<'a, 'tcx>(bcx: &BlockAndBuilder<'a, 'tcx>,
627627
if val_ty(llval) != Type::void(ccx) && machine::llsize_of_alloc(ccx, val_ty(llval)) != 0 {
628628
if let Some(ty) = fn_ty.ret.cast {
629629
let ptr = bcx.pointercast(llresult, ty.ptr_to());
630-
let store = bcx.store(llval, ptr);
631-
unsafe {
632-
llvm::LLVMSetAlignment(store, type_of::align_of(ccx, ret_ty));
633-
}
630+
bcx.store(llval, ptr, Some(type_of::align_of(ccx, ret_ty)));
634631
} else {
635632
store_ty(bcx, llval, llresult, ret_ty);
636633
}
@@ -697,7 +694,7 @@ fn try_intrinsic<'a, 'tcx>(
697694
) {
698695
if bcx.sess().no_landing_pads() {
699696
bcx.call(func, &[data], None);
700-
bcx.store(C_null(Type::i8p(&bcx.ccx)), dest);
697+
bcx.store(C_null(Type::i8p(&bcx.ccx)), dest, None);
701698
} else if wants_msvc_seh(bcx.sess()) {
702699
trans_msvc_try(bcx, func, data, local_ptr, dest);
703700
} else {
@@ -791,8 +788,8 @@ fn trans_msvc_try<'a, 'tcx>(bcx: &BlockAndBuilder<'a, 'tcx>,
791788
let val1 = C_i32(ccx, 1);
792789
let arg2 = catchpad.load(catchpad.inbounds_gep(addr, &[val1]));
793790
let local_ptr = catchpad.bitcast(local_ptr, i64p);
794-
catchpad.store(arg1, local_ptr);
795-
catchpad.store(arg2, catchpad.inbounds_gep(local_ptr, &[val1]));
791+
catchpad.store(arg1, local_ptr, None);
792+
catchpad.store(arg2, catchpad.inbounds_gep(local_ptr, &[val1]), None);
796793
catchpad.catch_ret(tok, caught.llbb());
797794

798795
caught.ret(C_i32(ccx, 1));
@@ -801,7 +798,7 @@ fn trans_msvc_try<'a, 'tcx>(bcx: &BlockAndBuilder<'a, 'tcx>,
801798
// Note that no invoke is used here because by definition this function
802799
// can't panic (that's what it's catching).
803800
let ret = bcx.call(llfn, &[func, data, local_ptr], None);
804-
bcx.store(ret, dest);
801+
bcx.store(ret, dest, None);
805802
}
806803

807804
// Definition of the standard "try" function for Rust using the GNU-like model
@@ -860,14 +857,14 @@ fn trans_gnu_try<'a, 'tcx>(bcx: &BlockAndBuilder<'a, 'tcx>,
860857
let vals = catch.landing_pad(lpad_ty, bcx.ccx.eh_personality(), 1, catch.fcx().llfn);
861858
catch.add_clause(vals, C_null(Type::i8p(ccx)));
862859
let ptr = catch.extract_value(vals, 0);
863-
catch.store(ptr, catch.bitcast(local_ptr, Type::i8p(ccx).ptr_to()));
860+
catch.store(ptr, catch.bitcast(local_ptr, Type::i8p(ccx).ptr_to()), None);
864861
catch.ret(C_i32(ccx, 1));
865862
});
866863

867864
// Note that no invoke is used here because by definition this function
868865
// can't panic (that's what it's catching).
869866
let ret = bcx.call(llfn, &[func, data, local_ptr], None);
870-
bcx.store(ret, dest);
867+
bcx.store(ret, dest, None);
871868
}
872869

873870
// Helper function to give a Block to a closure to translate a shim function.

src/librustc_trans/mir/block.rs

+11-6
Original file line numberDiff line numberDiff line change
@@ -23,14 +23,16 @@ use consts;
2323
use Disr;
2424
use machine::{llalign_of_min, llbitsize_of_real};
2525
use meth;
26-
use type_of;
26+
use type_of::{self, align_of};
2727
use glue;
2828
use type_::Type;
2929

3030
use rustc_data_structures::indexed_vec::IndexVec;
3131
use rustc_data_structures::fx::FxHashMap;
3232
use syntax::symbol::Symbol;
3333

34+
use std::cmp;
35+
3436
use super::{MirContext, LocalRef};
3537
use super::analyze::CleanupKind;
3638
use super::constant::Const;
@@ -207,7 +209,7 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
207209
let llslot = match op.val {
208210
Immediate(_) | Pair(..) => {
209211
let llscratch = bcx.fcx().alloca(ret.original_ty, "ret");
210-
self.store_operand(&bcx, llscratch, op);
212+
self.store_operand(&bcx, llscratch, op, None);
211213
llscratch
212214
}
213215
Ref(llval) => llval
@@ -424,7 +426,7 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
424426
// The first argument is a thin destination pointer.
425427
let llptr = self.trans_operand(&bcx, &args[0]).immediate();
426428
let val = self.trans_operand(&bcx, &args[1]);
427-
self.store_operand(&bcx, llptr, val);
429+
self.store_operand(&bcx, llptr, val, None);
428430
funclet_br(self, bcx, target);
429431
return;
430432
}
@@ -657,7 +659,7 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
657659
Immediate(_) | Pair(..) => {
658660
if arg.is_indirect() || arg.cast.is_some() {
659661
let llscratch = bcx.fcx().alloca(arg.original_ty, "arg");
660-
self.store_operand(bcx, llscratch, op);
662+
self.store_operand(bcx, llscratch, op, None);
661663
(llscratch, true)
662664
} else {
663665
(op.pack_if_pair(bcx).immediate(), false)
@@ -799,7 +801,7 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
799801
let llretval = bcx.landing_pad(llretty, llpersonality, 1, self.fcx.llfn);
800802
bcx.set_cleanup(llretval);
801803
let slot = self.get_personality_slot(&bcx);
802-
bcx.store(llretval, slot);
804+
bcx.store(llretval, slot, None);
803805
bcx.br(target.llbb());
804806
bcx.llbb()
805807
}
@@ -884,7 +886,10 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
884886

885887
let llty = type_of::type_of(bcx.ccx, val.ty);
886888
let cast_ptr = bcx.pointercast(dst.llval, llty.ptr_to());
887-
self.store_operand(bcx, cast_ptr, val);
889+
let in_type = val.ty;
890+
let out_type = dst.ty.to_ty(bcx.tcx());;
891+
let llalign = cmp::min(align_of(bcx.ccx, in_type), align_of(bcx.ccx, out_type));
892+
self.store_operand(bcx, cast_ptr, val, Some(llalign));
888893
}
889894

890895

src/librustc_trans/mir/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -515,7 +515,7 @@ fn arg_local_refs<'a, 'tcx>(bcx: &BlockAndBuilder<'a, 'tcx>,
515515
// environment into its components so it ends up out of bounds.
516516
let env_ptr = if !env_ref {
517517
let alloc = bcx.fcx().alloca(common::val_ty(llval), "__debuginfo_env_ptr");
518-
bcx.store(llval, alloc);
518+
bcx.store(llval, alloc, None);
519519
alloc
520520
} else {
521521
llval

src/librustc_trans/mir/operand.rs

+9-6
Original file line numberDiff line numberDiff line change
@@ -244,21 +244,24 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
244244
pub fn store_operand(&mut self,
245245
bcx: &BlockAndBuilder<'a, 'tcx>,
246246
lldest: ValueRef,
247-
operand: OperandRef<'tcx>) {
248-
debug!("store_operand: operand={:?}", operand);
247+
operand: OperandRef<'tcx>,
248+
align: Option<u32>) {
249+
debug!("store_operand: operand={:?}, align={:?}", operand, align);
249250
// Avoid generating stores of zero-sized values, because the only way to have a zero-sized
250251
// value is through `undef`, and store itself is useless.
251252
if common::type_is_zero_size(bcx.ccx, operand.ty) {
252253
return;
253254
}
254255
match operand.val {
255-
OperandValue::Ref(r) => base::memcpy_ty(bcx, lldest, r, operand.ty),
256-
OperandValue::Immediate(s) => base::store_ty(bcx, s, lldest, operand.ty),
256+
OperandValue::Ref(r) => base::memcpy_ty(bcx, lldest, r, operand.ty, align),
257+
OperandValue::Immediate(s) => {
258+
bcx.store(base::from_immediate(bcx, s), lldest, align);
259+
}
257260
OperandValue::Pair(a, b) => {
258261
let a = base::from_immediate(bcx, a);
259262
let b = base::from_immediate(bcx, b);
260-
bcx.store(a, bcx.struct_gep(lldest, 0));
261-
bcx.store(b, bcx.struct_gep(lldest, 1));
263+
bcx.store(a, bcx.struct_gep(lldest, 0), align);
264+
bcx.store(b, bcx.struct_gep(lldest, 1), align);
262265
}
263266
}
264267
}

0 commit comments

Comments
 (0)