Fixes #50371.
bx.pointercast(dst.llval, Type::i8p(cx)),
bx.pointercast(llscratch, Type::i8p(cx)),
C_usize(cx, self.layout.size.bytes()),
- self.layout.align.min(scratch_align));
+ self.layout.align.min(scratch_align),
+ false);
bx.lifetime_end(llscratch, scratch_size);
}
if src_f.layout.ty == dst_f.layout.ty {
memcpy_ty(bx, dst_f.llval, src_f.llval, src_f.layout,
- src_f.align.min(dst_f.align));
+ src_f.align.min(dst_f.align), false);
} else {
coerce_unsized_into(bx, src_f, dst_f);
}
dst: ValueRef,
src: ValueRef,
n_bytes: ValueRef,
- align: Align) {
+ align: Align,
+ volatile: bool) {
let cx = bx.cx;
let ptr_width = &cx.sess().target.target.target_pointer_width;
let key = format!("llvm.memcpy.p0i8.p0i8.i{}", ptr_width);
let dst_ptr = bx.pointercast(dst, Type::i8p(cx));
let size = bx.intcast(n_bytes, cx.isize_ty, false);
let align = C_i32(cx, align.abi() as i32);
- let volatile = C_bool(cx, false);
+ let volatile = C_bool(cx, volatile);
bx.call(memcpy, &[dst_ptr, src_ptr, size, align, volatile], None);
}
src: ValueRef,
layout: TyLayout<'tcx>,
align: Align,
+ volatile: bool,
) {
let size = layout.size.bytes();
if size == 0 {
return;
}
- call_memcpy(bx, dst, src, C_usize(bx.cx, size), align);
+ call_memcpy(bx, dst, src, C_usize(bx.cx, size), align, volatile);
}
pub fn call_memset<'a, 'tcx>(bx: &Builder<'a, 'tcx>,
}
}
- pub fn volatile_store(&self, val: ValueRef, ptr: ValueRef) -> ValueRef {
+ pub fn volatile_store(&self, val: ValueRef, ptr: ValueRef, align: Align) -> ValueRef {
debug!("Store {:?} -> {:?}", Value(val), Value(ptr));
assert!(!self.llbuilder.is_null());
self.count_insn("store.volatile");
let ptr = self.check_store(val, ptr);
unsafe {
let insn = llvm::LLVMBuildStore(self.llbuilder, val, ptr);
+ llvm::LLVMSetAlignment(insn, align.abi() as c_uint);
llvm::LLVMSetVolatile(insn, llvm::True);
insn
}
to_immediate(bx, load, cx.layout_of(tp_ty))
},
"volatile_store" => {
- let tp_ty = substs.type_at(0);
let dst = args[0].deref(bx.cx);
- if let OperandValue::Pair(a, b) = args[1].val {
- bx.volatile_store(a, dst.project_field(bx, 0).llval);
- bx.volatile_store(b, dst.project_field(bx, 1).llval);
- } else {
- let val = if let OperandValue::Ref(ptr, align) = args[1].val {
- bx.load(ptr, align)
- } else {
- if dst.layout.is_zst() {
- return;
- }
- from_immediate(bx, args[1].immediate())
- };
- let ptr = bx.pointercast(dst.llval, val_ty(val).ptr_to());
- let store = bx.volatile_store(val, ptr);
- unsafe {
- llvm::LLVMSetAlignment(store, cx.align_of(tp_ty).abi() as u32);
- }
+ if dst.layout.is_zst() {
+ return;
}
+ args[1].val.volatile_store(bx, dst);
return;
},
"prefetch_read_data" | "prefetch_write_data" |
// have scary latent bugs around.
let scratch = PlaceRef::alloca(bx, arg.layout, "arg");
- base::memcpy_ty(bx, scratch.llval, llval, op.layout, align);
+ base::memcpy_ty(bx, scratch.llval, llval, op.layout, align, false);
(scratch.llval, scratch.align, true)
} else {
(llval, align, true)
impl<'a, 'tcx> OperandValue {
pub fn store(self, bx: &Builder<'a, 'tcx>, dest: PlaceRef<'tcx>) {
+ self.store_maybe_volatile(bx, dest, false);
+ }
+
+ pub fn volatile_store(self, bx: &Builder<'a, 'tcx>, dest: PlaceRef<'tcx>) {
+ self.store_maybe_volatile(bx, dest, true);
+ }
+
+ fn store_maybe_volatile(self, bx: &Builder<'a, 'tcx>, dest: PlaceRef<'tcx>, volatile: bool) {
debug!("OperandRef::store: operand={:?}, dest={:?}", self, dest);
// Avoid generating stores of zero-sized values, because the only way to have a zero-sized
// value is through `undef`, and store itself is useless.
match self {
OperandValue::Ref(r, source_align) =>
base::memcpy_ty(bx, dest.llval, r, dest.layout,
- source_align.min(dest.align)),
+ source_align.min(dest.align), volatile),
OperandValue::Immediate(s) => {
- bx.store(base::from_immediate(bx, s), dest.llval, dest.align);
+ let val = base::from_immediate(bx, s);
+ if !volatile {
+ bx.store(val, dest.llval, dest.align);
+ } else {
+ bx.volatile_store(val, dest.llval, dest.align);
+ }
}
OperandValue::Pair(a, b) => {
for (i, &x) in [a, b].iter().enumerate() {
if common::val_ty(x) == Type::i1(bx.cx) {
llptr = bx.pointercast(llptr, Type::i8p(bx.cx));
}
- bx.store(base::from_immediate(bx, x), llptr, dest.align);
+ let val = base::from_immediate(bx, x);
+ if !volatile {
+ bx.store(val, llptr, dest.align);
+ } else {
+ bx.volatile_store(val, llptr, dest.align);
+ }
}
}
}