@@ -11,7 +11,7 @@ use rustc_ast::Mutability;
1111use rustc_hir:: def_id:: DefId ;
1212use rustc_middle:: mir:: AssertMessage ;
1313use rustc_session:: Limit ;
14- use rustc_span:: symbol:: Symbol ;
14+ use rustc_span:: symbol:: { sym , Symbol } ;
1515
1616use crate :: interpret:: {
1717 self , compile_time_machine, AllocId , Allocation , Frame , GlobalId , ImmTy , InterpCx ,
@@ -176,6 +176,38 @@ impl interpret::MayLeak for ! {
176176 }
177177}
178178
179+ impl < ' mir , ' tcx : ' mir > CompileTimeEvalContext < ' mir , ' tcx > {
180+ fn guaranteed_eq ( & mut self , a : Scalar , b : Scalar ) -> bool {
181+ match ( a, b) {
182+ // Comparisons between integers are always known.
183+ ( Scalar :: Raw { .. } , Scalar :: Raw { .. } ) => a == b,
184+ // Equality with integers can never be known for sure.
185+ ( Scalar :: Raw { .. } , Scalar :: Ptr ( _) ) | ( Scalar :: Ptr ( _) , Scalar :: Raw { .. } ) => false ,
186+ // FIXME: return `true` for when both sides are the same pointer, *except* that
187+ // some things (like functions and vtables) do not have stable addresses
188+ // so we need to be careful around them (see e.g. #73722).
189+ ( Scalar :: Ptr ( _) , Scalar :: Ptr ( _) ) => false ,
190+ }
191+ }
192+
193+ fn guaranteed_ne ( & mut self , a : Scalar , b : Scalar ) -> bool {
194+ match ( a, b) {
195+ // Comparisons between integers are always known.
196+ ( Scalar :: Raw { .. } , Scalar :: Raw { .. } ) => a != b,
197+ // Comparisons of abstract pointers with null pointers are known if the pointer
198+ // is in bounds, because if they are in bounds, the pointer can't be null.
199+ ( Scalar :: Raw { data : 0 , .. } , Scalar :: Ptr ( ptr) )
200+ | ( Scalar :: Ptr ( ptr) , Scalar :: Raw { data : 0 , .. } ) => !self . memory . ptr_may_be_null ( ptr) ,
201+ // Inequality with integers other than null can never be known for sure.
202+ ( Scalar :: Raw { .. } , Scalar :: Ptr ( _) ) | ( Scalar :: Ptr ( _) , Scalar :: Raw { .. } ) => false ,
203+ // FIXME: return `true` for at least some comparisons where we can reliably
204+ // determine the result of runtime inequality tests at compile-time.
205+ // Examples include comparison of addresses in different static items.
206+ ( Scalar :: Ptr ( _) , Scalar :: Ptr ( _) ) => false ,
207+ }
208+ }
209+ }
210+
179211impl < ' mir , ' tcx > interpret:: Machine < ' mir , ' tcx > for CompileTimeInterpreter < ' mir , ' tcx > {
180212 compile_time_machine ! ( <' mir, ' tcx>) ;
181213
@@ -234,12 +266,45 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
234266 ret : Option < ( PlaceTy < ' tcx > , mir:: BasicBlock ) > ,
235267 _unwind : Option < mir:: BasicBlock > ,
236268 ) -> InterpResult < ' tcx > {
269+ // Shared intrinsics.
237270 if ecx. emulate_intrinsic ( instance, args, ret) ? {
238271 return Ok ( ( ) ) ;
239272 }
240- // An intrinsic that we do not support
241273 let intrinsic_name = ecx. tcx . item_name ( instance. def_id ( ) ) ;
242- Err ( ConstEvalErrKind :: NeedsRfc ( format ! ( "calling intrinsic `{}`" , intrinsic_name) ) . into ( ) )
274+
275+ // CTFE-specific intrinsics.
276+ let ( dest, ret) = match ret {
277+ None => {
278+ return Err ( ConstEvalErrKind :: NeedsRfc ( format ! (
279+ "calling intrinsic `{}`" ,
280+ intrinsic_name
281+ ) )
282+ . into ( ) ) ;
283+ }
284+ Some ( p) => p,
285+ } ;
286+ match intrinsic_name {
287+ sym:: ptr_guaranteed_eq | sym:: ptr_guaranteed_ne => {
288+ let a = ecx. read_immediate ( args[ 0 ] ) ?. to_scalar ( ) ?;
289+ let b = ecx. read_immediate ( args[ 1 ] ) ?. to_scalar ( ) ?;
290+ let cmp = if intrinsic_name == sym:: ptr_guaranteed_eq {
291+ ecx. guaranteed_eq ( a, b)
292+ } else {
293+ ecx. guaranteed_ne ( a, b)
294+ } ;
295+ ecx. write_scalar ( Scalar :: from_bool ( cmp) , dest) ?;
296+ }
297+ _ => {
298+ return Err ( ConstEvalErrKind :: NeedsRfc ( format ! (
299+ "calling intrinsic `{}`" ,
300+ intrinsic_name
301+ ) )
302+ . into ( ) ) ;
303+ }
304+ }
305+
306+ ecx. go_to_block ( ret) ;
307+ Ok ( ( ) )
243308 }
244309
245310 fn assert_panic (
0 commit comments