Skip to content

Commit e276dda

Browse files
Centri3NCGThompson
authored andcommitted
Add miri test and make it operate on ptr
1 parent 5657b28 commit e276dda

File tree

13 files changed

+71
-80
lines changed

13 files changed

+71
-80
lines changed

compiler/rustc_codegen_llvm/src/context.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -908,7 +908,10 @@ impl<'ll> CodegenCx<'ll, '_> {
908908
ifn!("llvm.lifetime.start.p0i8", fn(t_i64, ptr) -> void);
909909
ifn!("llvm.lifetime.end.p0i8", fn(t_i64, ptr) -> void);
910910

911-
ifn!("llvm.is.constant", fn(...) -> i1);
911+
// Defining only the `ptr` variant of this overloaded intrinsic means
912+
// we can call this on any type we want (that doesn't ICE), but at the
913+
// slight cost of needing to write `addr_of!` everywhere.
914+
ifn!("llvm.is.constant.ptr", fn(ptr) -> i1);
912915

913916
ifn!("llvm.expect.i1", fn(i1, i1) -> i1);
914917
ifn!("llvm.eh.typeid.for", fn(ptr) -> t_i32);

compiler/rustc_codegen_llvm/src/intrinsic.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -119,8 +119,8 @@ impl<'ll, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'_, 'll, 'tcx> {
119119
sym::likely => {
120120
self.call_intrinsic("llvm.expect.i1", &[args[0].immediate(), self.const_bool(true)])
121121
}
122-
sym::is_compile_time_known => {
123-
self.call_intrinsic("llvm.is.constant", &[args[0].immediate()])
122+
sym::is_val_statically_known => {
123+
self.call_intrinsic("llvm.is.constant.ptr", &[args[0].immediate()])
124124
}
125125
sym::unlikely => self
126126
.call_intrinsic("llvm.expect.i1", &[args[0].immediate(), self.const_bool(false)]),

compiler/rustc_const_eval/src/const_eval/machine.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -531,7 +531,12 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
531531
)?;
532532
}
533533
}
534-
sym::is_compile_time_known => ecx.write_scalar(Scalar::from_bool(false), dest)?,
534+
// The name of this intrinsic is actually misleading. It actually
535+
// represents whether the value is known to the optimizer (LLVM).
536+
// The value of `arg`, while known to the machine, should be
537+
// considered unknown to the optimizer as we haven't gotten to the
538+
// codegen stage or ran any sort of optimizations yet.
539+
sym::is_val_statically_known => ecx.write_scalar(Scalar::from_bool(false), dest)?,
535540
_ => {
536541
throw_unsup_format!(
537542
"intrinsic `{intrinsic_name}` is not supported at compile-time"

compiler/rustc_const_eval/src/interpret/intrinsics.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,6 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
216216
sym::copy => {
217217
self.copy_intrinsic(&args[0], &args[1], &args[2], /*nonoverlapping*/ false)?;
218218
}
219-
sym::is_compile_time_known => self.write_scalar(Scalar::from_bool(false), dest)?,
220219
sym::write_bytes => {
221220
self.write_bytes_intrinsic(&args[0], &args[1], &args[2])?;
222221
}

compiler/rustc_hir_analysis/src/check/intrinsic.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -453,7 +453,9 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
453453

454454
sym::black_box => (1, vec![param(0)], param(0)),
455455

456-
sym::is_compile_time_known => (1, vec![param(0)], tcx.types.bool),
456+
sym::is_val_statically_known => {
457+
(1, vec![Ty::new_imm_ptr(tcx, param(0))], tcx.types.bool)
458+
}
457459

458460
sym::const_eval_select => (4, vec![param(0), param(1), param(2)], param(3)),
459461

compiler/rustc_span/src/symbol.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -907,7 +907,7 @@ symbols! {
907907
io_stderr,
908908
io_stdout,
909909
irrefutable_let_patterns,
910-
is_compile_time_known,
910+
is_val_statically_known,
911911
isa_attribute,
912912
isize,
913913
issue,

library/core/src/intrinsics.rs

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2512,11 +2512,12 @@ extern "rust-intrinsic" {
25122512
G: FnOnce<ARG, Output = RET>,
25132513
F: FnOnce<ARG, Output = RET>;
25142514

2515-
/// Returns whether the argument is known at compile-time.
2515+
/// Returns whether the argument's value is statically known at
2516+
/// compile-time.
25162517
///
25172518
/// This is useful when there is a way of writing the code that will
25182519
/// be *faster* when some variables have known values, but *slower*
2519-
/// in the general case: an `if is_compile_time_known(var)` can be used
2520+
/// in the general case: an `if is_val_statically_known(var)` can be used
25202521
/// to select between these two variants. The `if` will be optimized away
25212522
/// and only the desired branch remains.
25222523
///
@@ -2525,16 +2526,35 @@ extern "rust-intrinsic" {
25252526
/// In other words, the following code has *Undefined Behavior*:
25262527
///
25272528
/// ```rust
2528-
/// if !is_compile_time_known(0) { unreachable_unchecked(); }
2529+
/// if !is_val_statically_known(0) { unreachable_unchecked(); }
25292530
/// ```
25302531
///
2531-
/// Unsafe code may not rely on `is_compile_time_known` returning any
2532+
/// This also means that the following code's behavior is unspecified; it
2533+
/// may panic, or it may not:
2534+
///
2535+
/// ```rust,no_run
2536+
/// assert_eq!(is_val_statically_known(0), black_box(is_val_statically_known(0)))
2537+
/// ```
2538+
///
2539+
/// Unsafe code may not rely on `is_val_statically_known` returning any
25322540
/// particular value, ever. However, the compiler will generally make it
25332541
/// return `true` only if the value of the argument is actually known.
2534-
#[rustc_const_unstable(feature = "is_compile_time_known", issue = "none")]
2542+
///
2543+
/// When calling this in a `const fn`, both paths must be semantically
2544+
/// equivalent, that is, the result of the `true` branch and the `false`
2545+
/// branch return the same value *no matter what*.
2546+
#[rustc_const_unstable(feature = "is_val_statically_known", issue = "none")]
25352547
#[rustc_nounwind]
25362548
#[cfg(not(bootstrap))]
2537-
pub fn is_compile_time_known<T>(arg: T) -> bool;
2549+
pub fn is_val_statically_known<T>(arg: *const T) -> bool;
2550+
}
2551+
2552+
// FIXME: Seems using `unstable` here completely ignores `rustc_allow_const_fn_unstable`
2553+
// and thus compiling stage0 core doesn't work.
2554+
#[rustc_const_stable(feature = "is_val_statically_known", since = "never")]
2555+
#[cfg(bootstrap)]
2556+
pub const unsafe fn is_val_statically_known<T>(_: *const T) -> bool {
2557+
false
25382558
}
25392559

25402560
// Some functions are defined here because they accidentally got made

library/core/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,7 @@
197197
//
198198
// Language features:
199199
// tidy-alphabetical-start
200-
#![cfg_attr(not(bootstrap), feature(is_compile_time_known))]
200+
#![cfg_attr(not(bootstrap), feature(is_val_statically_known))]
201201
#![feature(abi_unadjusted)]
202202
#![feature(adt_const_params)]
203203
#![feature(allow_internal_unsafe)]

library/core/src/num/int_macros.rs

Lines changed: 2 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -2088,11 +2088,10 @@ macro_rules! int_impl {
20882088
without modifying the original"]
20892089
#[inline]
20902090
#[rustc_inherit_overflow_checks]
2091-
#[rustc_allow_const_fn_unstable(is_compile_time_known)]
2091+
#[rustc_allow_const_fn_unstable(is_val_statically_known)]
20922092
pub const fn pow(self, mut exp: u32) -> Self {
2093-
#[cfg(not(bootstrap))]
20942093
// SAFETY: This path has the same behavior as the other.
2095-
if unsafe { intrinsics::is_compile_time_known(self) }
2094+
if unsafe { intrinsics::is_val_statically_known(ptr::addr_of!(self)) }
20962095
&& self > 0
20972096
&& (self & (self - 1) == 0)
20982097
{
@@ -2132,29 +2131,6 @@ macro_rules! int_impl {
21322131
// needless overflow.
21332132
acc * base
21342133
}
2135-
2136-
#[cfg(bootstrap)]
2137-
{
2138-
if exp == 0 {
2139-
return 1;
2140-
}
2141-
let mut base = self;
2142-
let mut acc = 1;
2143-
2144-
while exp > 1 {
2145-
if (exp & 1) == 1 {
2146-
acc = acc * base;
2147-
}
2148-
exp /= 2;
2149-
base = base * base;
2150-
}
2151-
2152-
// since exp!=0, finally the exp must be 1.
2153-
// Deal with the final bit of the exponent separately, since
2154-
// squaring the base afterwards is not necessary and may cause a
2155-
// needless overflow.
2156-
acc * base
2157-
}
21582134
}
21592135

21602136
/// Returns the square root of the number, rounded down.

library/core/src/num/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ use crate::ascii;
66
use crate::intrinsics;
77
use crate::mem;
88
use crate::ops::{Add, Mul, Sub};
9+
use crate::ptr;
910
use crate::str::FromStr;
1011

1112
// Used because the `?` operator is not allowed in a const context.

library/core/src/num/uint_macros.rs

Lines changed: 4 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1973,7 +1973,7 @@ macro_rules! uint_impl {
19731973
without modifying the original"]
19741974
#[inline]
19751975
#[rustc_inherit_overflow_checks]
1976-
#[rustc_allow_const_fn_unstable(is_compile_time_known)]
1976+
#[rustc_allow_const_fn_unstable(is_val_statically_known)]
19771977
pub const fn pow(self, mut exp: u32) -> Self {
19781978
// LLVM now knows that `self` is a constant value, but not a
19791979
// constant in Rust. This allows us to compute the power used at
@@ -1986,9 +1986,10 @@ macro_rules! uint_impl {
19861986
// get the power of a power of two and the exponent through a `shl`
19871987
// instruction, but we must add a couple more checks for parity with
19881988
// our own `pow`.
1989-
#[cfg(not(bootstrap))]
19901989
// SAFETY: This path has the same behavior as the other.
1991-
if unsafe { intrinsics::is_compile_time_known(self) } && self.is_power_of_two() {
1990+
if unsafe { intrinsics::is_val_statically_known(ptr::addr_of!(self)) }
1991+
&& self.is_power_of_two()
1992+
{
19921993
let power_used = match self.checked_ilog2() {
19931994
Some(v) => v,
19941995
// SAFETY: We just checked this is a power of two. `0` is not a
@@ -2026,29 +2027,6 @@ macro_rules! uint_impl {
20262027
// needless overflow.
20272028
acc * base
20282029
}
2029-
2030-
#[cfg(bootstrap)]
2031-
{
2032-
if exp == 0 {
2033-
return 1;
2034-
}
2035-
let mut base = self;
2036-
let mut acc = 1;
2037-
2038-
while exp > 1 {
2039-
if (exp & 1) == 1 {
2040-
acc = acc * base;
2041-
}
2042-
exp /= 2;
2043-
base = base * base;
2044-
}
2045-
2046-
// since exp!=0, finally the exp must be 1.
2047-
// Deal with the final bit of the exponent separately, since
2048-
// squaring the base afterwards is not necessary and may cause a
2049-
// needless overflow.
2050-
acc * base
2051-
}
20522030
}
20532031

20542032
/// Returns the square root of the number, rounded down.

src/tools/miri/src/shims/intrinsics/mod.rs

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use std::iter;
55

66
use log::trace;
77

8+
use rand::Rng;
89
use rustc_apfloat::{Float, Round};
910
use rustc_middle::ty::layout::LayoutOf;
1011
use rustc_middle::{
@@ -141,16 +142,15 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
141142
this.write_pointer(Pointer::new(ptr.provenance, masked_addr), dest)?;
142143
}
143144

144-
// The default implementation always returns `false`, but we want
145-
// to return either `true` or `false` at random.
146-
"is_comptile_time_known" => {
147-
let rand = 0;
148-
_ = getrandom::getrandom(&mut [rand]);
149-
150-
this.write_scalar(
151-
Scalar::from_bool(if (rand % 1) == 1 { true } else { false }),
152-
dest,
153-
)?;
145+
// We want to return either `true` or `false` at random, or else something like
146+
// ```
147+
// if !is_val_statically_known(0) { unreachable_unchecked(); }
148+
// ```
149+
// Would not be considered UB, or the other way around (`is_val_statically_known(0)`).
150+
"is_val_statically_known" => {
151+
let [_] = check_arg_count(args)?;
152+
let branch = this.machine.rng.get_mut().gen();
153+
this.write_scalar(Scalar::from_bool(branch), dest)?;
154154
}
155155

156156
// Floating-point operations
@@ -477,10 +477,11 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
477477
}
478478
}
479479
// Nothing else
480-
_ => span_bug!(
481-
this.cur_span(),
482-
"`float_to_int_unchecked` called with non-int output type {dest_ty:?}"
483-
),
480+
_ =>
481+
span_bug!(
482+
this.cur_span(),
483+
"`float_to_int_unchecked` called with non-int output type {dest_ty:?}"
484+
),
484485
})
485486
}
486487
>>>>>>> acbf90a9489 (Make MIRI choose the path randomly and rename the intrinsic)

src/tools/miri/tests/pass/intrinsics.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,12 @@ fn main() {
3333
assert_eq!(intrinsics::likely(false), false);
3434
assert_eq!(intrinsics::unlikely(true), true);
3535

36+
if unsafe { intrinsics::is_val_statically_known(&0 as _) } {
37+
0
38+
} else {
39+
0
40+
};
41+
3642
intrinsics::forget(Bomb);
3743

3844
let _v = intrinsics::discriminant_value(&Some(()));

0 commit comments

Comments
 (0)