]> git.lizzy.rs Git - rust.git/commitdiff
Introduce OperandValue::volatile_store and use it in the intrinsics
authorAnthony Ramine <n.oxyde@gmail.com>
Fri, 11 May 2018 09:26:51 +0000 (11:26 +0200)
committerAnthony Ramine <n.oxyde@gmail.com>
Sun, 13 May 2018 08:36:28 +0000 (10:36 +0200)
Fixes #50371.

src/librustc_trans/abi.rs
src/librustc_trans/base.rs
src/librustc_trans/builder.rs
src/librustc_trans/intrinsic.rs
src/librustc_trans/mir/block.rs
src/librustc_trans/mir/operand.rs

index 1838dae049ad7e1a18cb205ed7ce6648900e4ae0..c80d989e3cb18b74f73bffa4f05afc97f307e44a 100644 (file)
@@ -220,7 +220,8 @@ fn store(&self, bx: &Builder<'a, 'tcx>, val: ValueRef, dst: PlaceRef<'tcx>) {
                                   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);
             }
index 0dd1adbff86e0daf7f616c646dcee11b3748c856..65dce5f3ffbce15ad91613e0f6637d8ad7cdf106 100644 (file)
@@ -320,7 +320,7 @@ pub fn coerce_unsized_into<'a, 'tcx>(bx: &Builder<'a, 'tcx>,
 
                 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);
                 }
@@ -408,7 +408,8 @@ pub fn call_memcpy(bx: &Builder,
                    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);
@@ -417,7 +418,7 @@ pub fn call_memcpy(bx: &Builder,
     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);
 }
 
@@ -427,13 +428,14 @@ pub fn memcpy_ty<'a, 'tcx>(
     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>,
index db803ca8209d9c67870e9bd5da01d1e19b9450b9..49bcf9b88a065fccbe2b860dfe25b2680e1e1060 100644 (file)
@@ -590,13 +590,14 @@ pub fn store(&self, val: ValueRef, ptr: ValueRef, align: Align) -> ValueRef {
         }
     }
 
-    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
         }
index 49a207a2d8ab5b299f54812d1c45ea0bcf879fd2..65e211ae740bcd81809998210dbf7a8ff86a514a 100644 (file)
@@ -247,26 +247,11 @@ pub fn trans_intrinsic_call<'a, 'tcx>(bx: &Builder<'a, 'tcx>,
             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" |
index b666c2b211525713e762126a5a437160a7ca787b..df8807c318b17efe52ca78338b53efe4fafe5a38 100644 (file)
@@ -626,7 +626,7 @@ fn trans_argument(&mut self,
                     // 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)
index 432ac44e0a5660e2f33f90042b7912a065f4d3e0..f69661782915fe7ec176865626824d0362854061 100644 (file)
@@ -275,6 +275,14 @@ pub fn extract_field(&self, bx: &Builder<'a, 'tcx>, i: usize) -> OperandRef<'tcx
 
 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.
@@ -284,9 +292,14 @@ pub fn store(self, bx: &Builder<'a, 'tcx>, dest: PlaceRef<'tcx>) {
         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() {
@@ -295,7 +308,12 @@ pub fn store(self, bx: &Builder<'a, 'tcx>, dest: PlaceRef<'tcx>) {
                     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);
+                    }
                 }
             }
         }