about summary refs log tree commit diff
diff options
context:
space:
mode:
authorCamille GILLOT <gillot.camille@gmail.com>2023-10-22 14:49:00 +0000
committerCamille GILLOT <gillot.camille@gmail.com>2023-10-25 17:59:30 +0000
commitd80eb3a498fe6dea75ea37142aae81ba26783efc (patch)
tree8d5ff26465b7c3a64e392ac149ef71c8390ee3a8
parentc4cc9ca0603cfdf5921a82d929d680db94d1d072 (diff)
downloadrust-d80eb3a498fe6dea75ea37142aae81ba26783efc.tar.gz
rust-d80eb3a498fe6dea75ea37142aae81ba26783efc.zip
Verify that the alloc_id is Memory.
-rw-r--r--compiler/rustc_mir_transform/src/gvn.rs7
-rw-r--r--tests/mir-opt/gvn.indirect_static.GVN.panic-abort.diff19
-rw-r--r--tests/mir-opt/gvn.indirect_static.GVN.panic-unwind.diff19
-rw-r--r--tests/mir-opt/gvn.rs14
4 files changed, 58 insertions, 1 deletions
diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs
index cf8a0fdb97e..cfa315fe61a 100644
--- a/compiler/rustc_mir_transform/src/gvn.rs
+++ b/compiler/rustc_mir_transform/src/gvn.rs
@@ -90,6 +90,7 @@ use rustc_hir::def::DefKind;
 use rustc_index::bit_set::BitSet;
 use rustc_index::IndexVec;
 use rustc_macros::newtype_index;
+use rustc_middle::mir::interpret::GlobalAlloc;
 use rustc_middle::mir::visit::*;
 use rustc_middle::mir::*;
 use rustc_middle::ty::adjustment::PointerCoercion;
@@ -922,7 +923,11 @@ fn op_to_prop_const<'tcx>(
         let pointer = mplace.ptr().into_pointer_or_addr().ok()?;
         let (alloc_id, offset) = pointer.into_parts();
         intern_const_alloc_for_constprop(ecx, alloc_id).ok()?;
-        return Some(ConstValue::Indirect { alloc_id, offset });
+        if matches!(ecx.tcx.global_alloc(alloc_id), GlobalAlloc::Memory(_)) {
+            // `alloc_id` may point to a static. Codegen will choke on an `Indirect` with anything
+            // by `GlobalAlloc::Memory`, so do fall through to copying if needed.
+            return Some(ConstValue::Indirect { alloc_id, offset });
+        }
     }
 
     // Everything failed: create a new allocation to hold the data.
diff --git a/tests/mir-opt/gvn.indirect_static.GVN.panic-abort.diff b/tests/mir-opt/gvn.indirect_static.GVN.panic-abort.diff
new file mode 100644
index 00000000000..f853942bbb6
--- /dev/null
+++ b/tests/mir-opt/gvn.indirect_static.GVN.panic-abort.diff
@@ -0,0 +1,19 @@
+- // MIR for `indirect_static` before GVN
++ // MIR for `indirect_static` after GVN
+  
+  fn indirect_static() -> () {
+      let mut _0: ();
+      let mut _1: &std::option::Option<u8>;
+      let mut _2: u8;
+  
+      bb0: {
+          _1 = const {ALLOC0: &Option<u8>};
+          _2 = (((*_1) as variant#1).0: u8);
+          return;
+      }
+  }
+  
+  ALLOC0 (static: A, size: 2, align: 1) {
+      00 __                                           │ .░
+  }
+  
diff --git a/tests/mir-opt/gvn.indirect_static.GVN.panic-unwind.diff b/tests/mir-opt/gvn.indirect_static.GVN.panic-unwind.diff
new file mode 100644
index 00000000000..f853942bbb6
--- /dev/null
+++ b/tests/mir-opt/gvn.indirect_static.GVN.panic-unwind.diff
@@ -0,0 +1,19 @@
+- // MIR for `indirect_static` before GVN
++ // MIR for `indirect_static` after GVN
+  
+  fn indirect_static() -> () {
+      let mut _0: ();
+      let mut _1: &std::option::Option<u8>;
+      let mut _2: u8;
+  
+      bb0: {
+          _1 = const {ALLOC0: &Option<u8>};
+          _2 = (((*_1) as variant#1).0: u8);
+          return;
+      }
+  }
+  
+  ALLOC0 (static: A, size: 2, align: 1) {
+      00 __                                           │ .░
+  }
+  
diff --git a/tests/mir-opt/gvn.rs b/tests/mir-opt/gvn.rs
index 7ce851905e0..10a66ced026 100644
--- a/tests/mir-opt/gvn.rs
+++ b/tests/mir-opt/gvn.rs
@@ -597,6 +597,18 @@ fn fn_pointers() {
     opaque(cg);
 }
 
+/// Verify that we do not create a `ConstValue::Indirect` backed by a static's AllocId.
+#[custom_mir(dialect = "analysis")]
+fn indirect_static() {
+    static A: Option<u8> = None;
+
+    mir!({
+        let ptr = Static(A);
+        let out = Field::<u8>(Variant(*ptr, 1), 0);
+        Return()
+    })
+}
+
 fn main() {
     subexpression_elimination(2, 4, 5);
     wrap_unwrap(5);
@@ -614,6 +626,7 @@ fn main() {
     assert_eq!(direct, indirect);
     repeat();
     fn_pointers();
+    indirect_static();
 }
 
 #[inline(never)]
@@ -639,3 +652,4 @@ fn identity<T>(x: T) -> T {
 // EMIT_MIR gvn.duplicate_slice.GVN.diff
 // EMIT_MIR gvn.repeat.GVN.diff
 // EMIT_MIR gvn.fn_pointers.GVN.diff
+// EMIT_MIR gvn.indirect_static.GVN.diff