@@ -11,7 +11,7 @@ use rustc_ast::Mutability;
11
11
use rustc_hir:: def_id:: DefId ;
12
12
use rustc_middle:: mir:: AssertMessage ;
13
13
use rustc_session:: Limit ;
14
- use rustc_span:: symbol:: Symbol ;
14
+ use rustc_span:: symbol:: { sym , Symbol } ;
15
15
16
16
use crate :: interpret:: {
17
17
self , compile_time_machine, AllocId , Allocation , Frame , GlobalId , ImmTy , InterpCx ,
@@ -176,6 +176,38 @@ impl interpret::MayLeak for ! {
176
176
}
177
177
}
178
178
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
+
179
211
impl < ' mir , ' tcx > interpret:: Machine < ' mir , ' tcx > for CompileTimeInterpreter < ' mir , ' tcx > {
180
212
compile_time_machine ! ( <' mir, ' tcx>) ;
181
213
@@ -234,12 +266,45 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
234
266
ret : Option < ( PlaceTy < ' tcx > , mir:: BasicBlock ) > ,
235
267
_unwind : Option < mir:: BasicBlock > ,
236
268
) -> InterpResult < ' tcx > {
269
+ // Shared intrinsics.
237
270
if ecx. emulate_intrinsic ( instance, args, ret) ? {
238
271
return Ok ( ( ) ) ;
239
272
}
240
- // An intrinsic that we do not support
241
273
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 ( ( ) )
243
308
}
244
309
245
310
fn assert_panic (
0 commit comments