about summary refs log tree commit diff
diff options
context:
space:
mode:
authorantoyo <antoyo@users.noreply.github.com>2023-10-24 21:34:17 -0400
committerGitHub <noreply@github.com>2023-10-24 21:34:17 -0400
commit3d9c8afc034ed8e1f6029099de3aec1f043d5f72 (patch)
treeddf9ee274258edb5b43a075a3720980fc199c4e9
parent46887f2a842d95e03c19ee4cade25e53635e7126 (diff)
parenta93d1b73c67f8d08d759a9a880a3bc0081d6ae16 (diff)
downloadrust-3d9c8afc034ed8e1f6029099de3aec1f043d5f72.tar.gz
rust-3d9c8afc034ed8e1f6029099de3aec1f043d5f72.zip
Merge pull request #365 from rust-lang/fix/volatile-load
Fix volatile_load
-rw-r--r--src/builder.rs5
-rw-r--r--src/intrinsic/mod.rs18
-rw-r--r--tests/run/volatile.rs26
3 files changed, 40 insertions, 9 deletions
diff --git a/src/builder.rs b/src/builder.rs
index b7841808934..b8a8c144dc9 100644
--- a/src/builder.rs
+++ b/src/builder.rs
@@ -751,9 +751,8 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
         loaded_value.to_rvalue()
     }
 
-    fn volatile_load(&mut self, _ty: Type<'gcc>, ptr: RValue<'gcc>) -> RValue<'gcc> {
-        // TODO(antoyo): use ty.
-        let ptr = self.context.new_cast(None, ptr, ptr.get_type().make_volatile());
+    fn volatile_load(&mut self, ty: Type<'gcc>, ptr: RValue<'gcc>) -> RValue<'gcc> {
+        let ptr = self.context.new_cast(None, ptr, ty.make_volatile().make_pointer());
         ptr.dereference(None).to_rvalue()
     }
 
diff --git a/src/intrinsic/mod.rs b/src/intrinsic/mod.rs
index bfe27c0552f..ba1cae03f3e 100644
--- a/src/intrinsic/mod.rs
+++ b/src/intrinsic/mod.rs
@@ -4,7 +4,9 @@ mod simd;
 #[cfg(feature="master")]
 use std::iter;
 
-use gccjit::{ComparisonOp, Function, RValue, ToRValue, Type, UnaryOp, FunctionType};
+#[cfg(feature="master")]
+use gccjit::FunctionType;
+use gccjit::{ComparisonOp, Function, RValue, ToRValue, Type, UnaryOp};
 use rustc_codegen_ssa::MemFlags;
 use rustc_codegen_ssa::base::wants_msvc_seh;
 use rustc_codegen_ssa::common::IntPredicate;
@@ -143,11 +145,15 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
 
                 sym::volatile_load | sym::unaligned_volatile_load => {
                     let tp_ty = fn_args.type_at(0);
-                    let mut ptr = args[0].immediate();
-                    if let PassMode::Cast { cast: ty, .. } = &fn_abi.ret.mode {
-                        ptr = self.pointercast(ptr, self.type_ptr_to(ty.gcc_type(self)));
-                    }
-                    let load = self.volatile_load(ptr.get_type(), ptr);
+                    let ptr = args[0].immediate();
+                    let load =
+                        if let PassMode::Cast { cast: ty, pad_i32: _ } = &fn_abi.ret.mode {
+                            let gcc_ty = ty.gcc_type(self);
+                            self.volatile_load(gcc_ty, ptr)
+                        }
+                        else {
+                            self.volatile_load(self.layout_of(tp_ty).gcc_type(self), ptr)
+                        };
                     // TODO(antoyo): set alignment.
                     self.to_immediate(load, self.layout_of(tp_ty))
                 }
diff --git a/tests/run/volatile.rs b/tests/run/volatile.rs
new file mode 100644
index 00000000000..8b043312593
--- /dev/null
+++ b/tests/run/volatile.rs
@@ -0,0 +1,26 @@
+// Compiler:
+//
+// Run-time:
+//   status: 0
+
+use std::mem::MaybeUninit;
+
+#[derive(Debug)]
+struct Struct {
+    pointer: *const (),
+    func: unsafe fn(*const ()),
+}
+
+fn func(ptr: *const ()) {
+}
+
+fn main() {
+    let mut x = MaybeUninit::<&Struct>::uninit();
+    x.write(&Struct {
+        pointer: std::ptr::null(),
+        func,
+    });
+    let x = unsafe { x.assume_init() };
+    let value = unsafe { (x as *const Struct).read_volatile() };
+    println!("{:?}", value);
+}