Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 7d7fe3f

Browse files
committed
Adjust for codegen of unpredictable return value
It seems important for LLVM that we select on the values by-value instead of reading and have no intermediate store. So make sure the guards selects both potential drops but defers the return value to the second selection. Since the two options alias we use raw mutable pointers instead of mutable references as before.
1 parent 21bdfa1 commit 7d7fe3f

File tree

1 file changed

+31
-5
lines changed

1 file changed

+31
-5
lines changed

‎library/core/src/hint.rs

Lines changed: 31 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -786,16 +786,42 @@ pub fn select_unpredictable<T>(condition: bool, true_val: T, false_val: T) -> T
786786
// Change this to use ManuallyDrop instead.
787787
let mut true_val = MaybeUninit::new(true_val);
788788
let mut false_val = MaybeUninit::new(false_val);
789+
790+
struct DropOnPanic<T> {
791+
inner: *mut MaybeUninit<T>,
792+
}
793+
794+
impl<T> Drop for DropOnPanic<T> {
795+
fn drop(&mut self) {
796+
// SAFETY: Must be guaranteed on construction of local type `DropOnPanic`.
797+
unsafe { (*self.inner).assume_init_drop() }
798+
}
799+
}
800+
801+
let true_ptr = (&mut true_val) as *mut _;
802+
let false_ptr = (&mut false_val) as *mut _;
803+
789804
// SAFETY: The value that is not selected is dropped, and the selected one
790805
// is returned. This is necessary because the intrinsic doesn't drop the
791806
// value that is not selected.
792807
unsafe {
793808
// Extract the selected value first, ensure it is dropped as well if dropping the unselected
794809
// value panics.
795-
let ret = crate::intrinsics::select_unpredictable(condition, &true_val, &false_val)
796-
.assume_init_read();
797-
crate::intrinsics::select_unpredictable(!condition, &mut true_val, &mut false_val)
798-
.assume_init_drop();
799-
ret
810+
let (guard, drop) = crate::intrinsics::select_unpredictable(
811+
condition,
812+
(true_ptr, false_ptr),
813+
(false_ptr, true_ptr),
814+
);
815+
816+
// SAFETY: both pointers are to valid `MaybeUninit`, in both variants they do not alias but
817+
// the two arguments we have selected from did alias each other.
818+
let guard = DropOnPanic { inner: guard };
819+
(*drop).assume_init_drop();
820+
crate::mem::forget(guard);
821+
822+
// Note that it is important to use the values here. Reading from the pointer we got makes
823+
// LLVM forget the !unpredictable annotation sometimes (in tests, integer sized values in
824+
// particular seemed to confuse it, also observed in llvm/llvm-project #82340).
825+
crate::intrinsics::select_unpredictable(condition, true_val, false_val).assume_init()
800826
}
801827
}

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /