]> git.lizzy.rs Git - rust.git/commitdiff
Add unaligned volatile intrinsics
authorAmanieu d'Antras <amanieu@gmail.com>
Sat, 14 Jul 2018 22:28:39 +0000 (23:28 +0100)
committerAmanieu d'Antras <amanieu@gmail.com>
Sat, 14 Jul 2018 22:28:39 +0000 (23:28 +0100)
src/libcore/intrinsics.rs
src/librustc_codegen_llvm/builder.rs
src/librustc_codegen_llvm/intrinsic.rs
src/librustc_codegen_llvm/mir/operand.rs
src/librustc_typeck/check/intrinsic.rs
src/test/run-make-fulldeps/volatile-intrinsics/main.rs

index 89fe2d941a350c0f84f5b212d41d92aa868e3288..854cb5f4e3b3f77a1791896e3f8df6d0eaba57dd 100644 (file)
@@ -1085,6 +1085,15 @@ pub fn volatile_copy_nonoverlapping_memory<T>(dst: *mut T, src: *const T,
     /// [`std::ptr::write_volatile`](../../std/ptr/fn.write_volatile.html).
     pub fn volatile_store<T>(dst: *mut T, val: T);
 
+    /// Perform a volatile load from the `src` pointer
+    /// The pointer is not required to be aligned.
+    #[cfg(not(stage0))]
+    pub fn unaligned_volatile_load<T>(src: *const T) -> T;
+    /// Perform a volatile store to the `dst` pointer.
+    /// The pointer is not required to be aligned.
+    #[cfg(not(stage0))]
+    pub fn unaligned_volatile_store<T>(dst: *mut T, val: T);
+
     /// Returns the square root of an `f32`
     pub fn sqrtf32(x: f32) -> f32;
     /// Returns the square root of an `f64`
index 7b4998e85881efa9a03ad31810021ce8b0a0d18d..c8dc579cd62e98f3581f67beafaa859216a1e277 100644 (file)
@@ -54,6 +54,7 @@ fn noname() -> *const c_char {
     pub struct MemFlags: u8 {
         const VOLATILE = 1 << 0;
         const NONTEMPORAL = 1 << 1;
+        const UNALIGNED = 1 << 2;
     }
 }
 
@@ -602,7 +603,12 @@ pub fn store_with_flags(
         let ptr = self.check_store(val, ptr);
         unsafe {
             let store = llvm::LLVMBuildStore(self.llbuilder, val, ptr);
-            llvm::LLVMSetAlignment(store, align.abi() as c_uint);
+            let align = if flags.contains(MemFlags::UNALIGNED) {
+                1
+            } else {
+                align.abi() as c_uint
+            };
+            llvm::LLVMSetAlignment(store, align);
             if flags.contains(MemFlags::VOLATILE) {
                 llvm::LLVMSetVolatile(store, llvm::True);
             }
index 6bb5456f9034f7ee91d3c45b24a8e6055b322a46..567595b699798f702dd4f8e1c0e40ee2574fcb94 100644 (file)
@@ -234,15 +234,20 @@ pub fn codegen_intrinsic_call<'a, 'tcx>(bx: &Builder<'a, 'tcx>,
             memset_intrinsic(bx, true, substs.type_at(0),
                              args[0].immediate(), args[1].immediate(), args[2].immediate())
         }
-        "volatile_load" => {
+        "volatile_load" | "unaligned_volatile_load" => {
             let tp_ty = substs.type_at(0);
             let mut ptr = args[0].immediate();
             if let PassMode::Cast(ty) = fn_ty.ret.mode {
                 ptr = bx.pointercast(ptr, ty.llvm_type(cx).ptr_to());
             }
             let load = bx.volatile_load(ptr);
+            let align = if name == "unaligned_volatile_load" {
+                1
+            } else {
+                cx.align_of(tp_ty).abi() as u32
+            };
             unsafe {
-                llvm::LLVMSetAlignment(load, cx.align_of(tp_ty).abi() as u32);
+                llvm::LLVMSetAlignment(load, align);
             }
             to_immediate(bx, load, cx.layout_of(tp_ty))
         },
@@ -251,6 +256,11 @@ pub fn codegen_intrinsic_call<'a, 'tcx>(bx: &Builder<'a, 'tcx>,
             args[1].val.volatile_store(bx, dst);
             return;
         },
+        "unaligned_volatile_store" => {
+            let dst = args[0].deref(bx.cx);
+            args[1].val.unaligned_volatile_store(bx, dst);
+            return;
+        },
         "prefetch_read_data" | "prefetch_write_data" |
         "prefetch_read_instruction" | "prefetch_write_instruction" => {
             let expect = cx.get_intrinsic(&("llvm.prefetch"));
index 3d3a4400bd8108abca11973e5693f839dbc5fc32..49cc07d6854a75324c38506dbdadddbc33b5a5d7 100644 (file)
@@ -286,6 +286,10 @@ pub fn volatile_store(self, bx: &Builder<'a, 'tcx>, dest: PlaceRef<'tcx>) {
         self.store_with_flags(bx, dest, MemFlags::VOLATILE);
     }
 
+    pub fn unaligned_volatile_store(self, bx: &Builder<'a, 'tcx>, dest: PlaceRef<'tcx>) {
+        self.store_with_flags(bx, dest, MemFlags::VOLATILE | MemFlags::UNALIGNED);
+    }
+
     pub fn nontemporal_store(self, bx: &Builder<'a, 'tcx>, dest: PlaceRef<'tcx>) {
         self.store_with_flags(bx, dest, MemFlags::NONTEMPORAL);
     }
index c93023edcea08285207dd94d67ac34959846ca6a..46cf9d1fa7fad3c84f9215d9e8b8cc528e5743de 100644 (file)
@@ -270,9 +270,9 @@ pub fn check_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
             "roundf32"     => (0, vec![ tcx.types.f32 ], tcx.types.f32),
             "roundf64"     => (0, vec![ tcx.types.f64 ], tcx.types.f64),
 
-            "volatile_load" =>
+            "volatile_load" | "unaligned_volatile_load" =>
                 (1, vec![ tcx.mk_imm_ptr(param(0)) ], param(0)),
-            "volatile_store" =>
+            "volatile_store" | "unaligned_volatile_store" =>
                 (1, vec![ tcx.mk_mut_ptr(param(0)), param(0) ], tcx.mk_nil()),
 
             "ctpop" | "ctlz" | "ctlz_nonzero" | "cttz" | "cttz_nonzero" |
index 4d0d7672101c36c4377fe04f5e806abb7ba0cb25..d214a20139c9ca8bfd597ed9c82247d08ebc7a8e 100644 (file)
 
 #![feature(core_intrinsics, volatile)]
 
-use std::intrinsics::{volatile_load, volatile_store};
+use std::intrinsics::{
+    unaligned_volatile_load, unaligned_volatile_store, volatile_load, volatile_store,
+};
 use std::ptr::{read_volatile, write_volatile};
 
 pub fn main() {
     unsafe {
-        let mut i : isize = 1;
+        let mut i: isize = 1;
         volatile_store(&mut i, 2);
         assert_eq!(volatile_load(&i), 2);
     }
     unsafe {
-        let mut i : isize = 1;
+        let mut i: isize = 1;
+        unaligned_volatile_store(&mut i, 2);
+        assert_eq!(unaligned_volatile_load(&i), 2);
+    }
+    unsafe {
+        let mut i: isize = 1;
         write_volatile(&mut i, 2);
         assert_eq!(read_volatile(&i), 2);
     }