mirror of
https://github.com/rust-lang/rust.git
synced 2025-06-05 11:48:30 +00:00
Clearly document intentional UB in mir-opt tests
Co-authored-by: Jakob Degen <jakob.e.degen@gmail.com>
This commit is contained in:
parent
8dabf5da9e
commit
614df3fd5e
@ -1,3 +1,13 @@
|
|||||||
|
// This attempts to mutate `a` via a pointer derived from `addr_of!(a)`. That is UB
|
||||||
|
// according to Miri. However, the decision to make this UB - and to allow
|
||||||
|
// rustc to rely on that fact for the purpose of optimizations - has not been
|
||||||
|
// finalized.
|
||||||
|
//
|
||||||
|
// As such, we include this test to ensure that copy prop does not rely on that
|
||||||
|
// fact. Specifically, if `addr_of!(a)` could not be used to modify a, it would
|
||||||
|
// be correct for CopyProp to replace all occurrences of `a` with `c` - but that
|
||||||
|
// would cause `f(true)` to output `false` instead of `true`.
|
||||||
|
|
||||||
#![feature(custom_mir, core_intrinsics)]
|
#![feature(custom_mir, core_intrinsics)]
|
||||||
#![allow(unused_assignments)]
|
#![allow(unused_assignments)]
|
||||||
extern crate core;
|
extern crate core;
|
||||||
|
@ -32,7 +32,7 @@
|
|||||||
_5 = _3; // scope 3 at $DIR/sibling_ptr.rs:+4:10: +4:11
|
_5 = _3; // scope 3 at $DIR/sibling_ptr.rs:+4:10: +4:11
|
||||||
_4 = ptr::mut_ptr::<impl *mut u8>::add(move _5, const 1_usize) -> bb1; // scope 3 at $DIR/sibling_ptr.rs:+4:10: +4:18
|
_4 = ptr::mut_ptr::<impl *mut u8>::add(move _5, const 1_usize) -> bb1; // scope 3 at $DIR/sibling_ptr.rs:+4:10: +4:18
|
||||||
// mir::Constant
|
// mir::Constant
|
||||||
// + span: $DIR/sibling_ptr.rs:8:12: 8:15
|
// + span: $DIR/sibling_ptr.rs:15:12: 15:15
|
||||||
// + literal: Const { ty: unsafe fn(*mut u8, usize) -> *mut u8 {ptr::mut_ptr::<impl *mut u8>::add}, val: Value(<ZST>) }
|
// + literal: Const { ty: unsafe fn(*mut u8, usize) -> *mut u8 {ptr::mut_ptr::<impl *mut u8>::add}, val: Value(<ZST>) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,3 +1,10 @@
|
|||||||
|
// This attempts to modify `x.1` via a pointer derived from `addr_of_mut!(x.0)`.
|
||||||
|
// According to Miri, that is UB. However, T-opsem has not finalized that
|
||||||
|
// decision and as such we cannot rely on it in optimizations. Consequently,
|
||||||
|
// DataflowConstProp must treat the `addr_of_mut!(x.0)` as potentially being
|
||||||
|
// used to modify `x.1` - if it did not, then it might incorrectly assume that it
|
||||||
|
// can infer the value of `x.1` at the end of this function.
|
||||||
|
|
||||||
// unit-test: DataflowConstProp
|
// unit-test: DataflowConstProp
|
||||||
|
|
||||||
// EMIT_MIR sibling_ptr.main.DataflowConstProp.diff
|
// EMIT_MIR sibling_ptr.main.DataflowConstProp.diff
|
||||||
@ -7,5 +14,5 @@ fn main() {
|
|||||||
let p = std::ptr::addr_of_mut!(x.0);
|
let p = std::ptr::addr_of_mut!(x.0);
|
||||||
*p.add(1) = 1;
|
*p.add(1) = 1;
|
||||||
}
|
}
|
||||||
let x1 = x.1; // should not be propagated
|
let x1 = x.1; // should not be propagated
|
||||||
}
|
}
|
||||||
|
@ -3,42 +3,42 @@
|
|||||||
|
|
||||||
fn escaping() -> () {
|
fn escaping() -> () {
|
||||||
let mut _0: (); // return place in scope 0 at $DIR/sroa.rs:+0:19: +0:19
|
let mut _0: (); // return place in scope 0 at $DIR/sroa.rs:+0:19: +0:19
|
||||||
let _1: (); // in scope 0 at $DIR/sroa.rs:+2:5: +2:42
|
let _1: (); // in scope 0 at $DIR/sroa.rs:+1:5: +1:42
|
||||||
let mut _2: *const u32; // in scope 0 at $DIR/sroa.rs:+2:7: +2:41
|
let mut _2: *const u32; // in scope 0 at $DIR/sroa.rs:+1:7: +1:41
|
||||||
let _3: &u32; // in scope 0 at $DIR/sroa.rs:+2:7: +2:41
|
let _3: &u32; // in scope 0 at $DIR/sroa.rs:+1:7: +1:41
|
||||||
let _4: Escaping; // in scope 0 at $DIR/sroa.rs:+2:8: +2:39
|
let _4: Escaping; // in scope 0 at $DIR/sroa.rs:+1:8: +1:39
|
||||||
let mut _5: u32; // in scope 0 at $DIR/sroa.rs:+2:34: +2:37
|
let mut _5: u32; // in scope 0 at $DIR/sroa.rs:+1:34: +1:37
|
||||||
|
|
||||||
bb0: {
|
bb0: {
|
||||||
StorageLive(_1); // scope 0 at $DIR/sroa.rs:+2:5: +2:42
|
StorageLive(_1); // scope 0 at $DIR/sroa.rs:+1:5: +1:42
|
||||||
StorageLive(_2); // scope 0 at $DIR/sroa.rs:+2:7: +2:41
|
StorageLive(_2); // scope 0 at $DIR/sroa.rs:+1:7: +1:41
|
||||||
StorageLive(_3); // scope 0 at $DIR/sroa.rs:+2:7: +2:41
|
StorageLive(_3); // scope 0 at $DIR/sroa.rs:+1:7: +1:41
|
||||||
StorageLive(_4); // scope 0 at $DIR/sroa.rs:+2:8: +2:39
|
StorageLive(_4); // scope 0 at $DIR/sroa.rs:+1:8: +1:39
|
||||||
StorageLive(_5); // scope 0 at $DIR/sroa.rs:+2:34: +2:37
|
StorageLive(_5); // scope 0 at $DIR/sroa.rs:+1:34: +1:37
|
||||||
_5 = g() -> bb1; // scope 0 at $DIR/sroa.rs:+2:34: +2:37
|
_5 = g() -> bb1; // scope 0 at $DIR/sroa.rs:+1:34: +1:37
|
||||||
// mir::Constant
|
// mir::Constant
|
||||||
// + span: $DIR/sroa.rs:73:34: 73:35
|
// + span: $DIR/sroa.rs:78:34: 78:35
|
||||||
// + literal: Const { ty: fn() -> u32 {g}, val: Value(<ZST>) }
|
// + literal: Const { ty: fn() -> u32 {g}, val: Value(<ZST>) }
|
||||||
}
|
}
|
||||||
|
|
||||||
bb1: {
|
bb1: {
|
||||||
_4 = Escaping { a: const 1_u32, b: const 2_u32, c: move _5 }; // scope 0 at $DIR/sroa.rs:+2:8: +2:39
|
_4 = Escaping { a: const 1_u32, b: const 2_u32, c: move _5 }; // scope 0 at $DIR/sroa.rs:+1:8: +1:39
|
||||||
StorageDead(_5); // scope 0 at $DIR/sroa.rs:+2:38: +2:39
|
StorageDead(_5); // scope 0 at $DIR/sroa.rs:+1:38: +1:39
|
||||||
_3 = &(_4.0: u32); // scope 0 at $DIR/sroa.rs:+2:7: +2:41
|
_3 = &(_4.0: u32); // scope 0 at $DIR/sroa.rs:+1:7: +1:41
|
||||||
_2 = &raw const (*_3); // scope 0 at $DIR/sroa.rs:+2:7: +2:41
|
_2 = &raw const (*_3); // scope 0 at $DIR/sroa.rs:+1:7: +1:41
|
||||||
_1 = f(move _2) -> bb2; // scope 0 at $DIR/sroa.rs:+2:5: +2:42
|
_1 = f(move _2) -> bb2; // scope 0 at $DIR/sroa.rs:+1:5: +1:42
|
||||||
// mir::Constant
|
// mir::Constant
|
||||||
// + span: $DIR/sroa.rs:73:5: 73:6
|
// + span: $DIR/sroa.rs:78:5: 78:6
|
||||||
// + literal: Const { ty: fn(*const u32) {f}, val: Value(<ZST>) }
|
// + literal: Const { ty: fn(*const u32) {f}, val: Value(<ZST>) }
|
||||||
}
|
}
|
||||||
|
|
||||||
bb2: {
|
bb2: {
|
||||||
StorageDead(_2); // scope 0 at $DIR/sroa.rs:+2:41: +2:42
|
StorageDead(_2); // scope 0 at $DIR/sroa.rs:+1:41: +1:42
|
||||||
StorageDead(_4); // scope 0 at $DIR/sroa.rs:+2:42: +2:43
|
StorageDead(_4); // scope 0 at $DIR/sroa.rs:+1:42: +1:43
|
||||||
StorageDead(_3); // scope 0 at $DIR/sroa.rs:+2:42: +2:43
|
StorageDead(_3); // scope 0 at $DIR/sroa.rs:+1:42: +1:43
|
||||||
StorageDead(_1); // scope 0 at $DIR/sroa.rs:+2:42: +2:43
|
StorageDead(_1); // scope 0 at $DIR/sroa.rs:+1:42: +1:43
|
||||||
_0 = const (); // scope 0 at $DIR/sroa.rs:+0:19: +3:2
|
_0 = const (); // scope 0 at $DIR/sroa.rs:+0:19: +2:2
|
||||||
return; // scope 0 at $DIR/sroa.rs:+3:2: +3:2
|
return; // scope 0 at $DIR/sroa.rs:+2:2: +2:2
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -68,8 +68,13 @@ fn f(a: *const u32) {
|
|||||||
println!("{}", unsafe { *a.add(2) });
|
println!("{}", unsafe { *a.add(2) });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// `f` uses the `&e.a` to access `e.c`. This is UB according to Miri today; however,
|
||||||
|
// T-opsem has not finalized that decision and as such rustc should not rely on
|
||||||
|
// it. If SROA were to rely on it, it would be (almost) correct to turn `e` into
|
||||||
|
// three distinct locals - one for each field - and pass a reference to only one
|
||||||
|
// of them to `f`. However, this would lead to a miscompilation because `b` and `c`
|
||||||
|
// might no longer appear right after `a` in memory.
|
||||||
pub fn escaping() {
|
pub fn escaping() {
|
||||||
// Verify this struct is not flattened.
|
|
||||||
f(&Escaping { a: 1, b: 2, c: g() }.a);
|
f(&Escaping { a: 1, b: 2, c: g() }.a);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user