@@ -11,6 +11,7 @@ use rustc_middle::{
11
11
ty:: { self , FloatTy } ,
12
12
} ;
13
13
use rustc_target:: abi:: Size ;
14
+ use rustc_span:: { sym, Symbol } ;
14
15
15
16
use crate :: * ;
16
17
use atomic:: EvalContextExt as _;
@@ -26,12 +27,12 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
26
27
dest : & MPlaceTy < ' tcx , Provenance > ,
27
28
ret : Option < mir:: BasicBlock > ,
28
29
_unwind : mir:: UnwindAction ,
29
- ) -> InterpResult < ' tcx > {
30
+ ) -> InterpResult < ' tcx , Option < ty :: Instance < ' tcx > > > {
30
31
let this = self . eval_context_mut ( ) ;
31
32
32
33
// See if the core engine can handle this intrinsic.
33
34
if this. emulate_intrinsic ( instance, args, dest, ret) ? {
34
- return Ok ( ( ) ) ;
35
+ return Ok ( None ) ;
35
36
}
36
37
let intrinsic_name = this. tcx . item_name ( instance. def_id ( ) ) ;
37
38
let intrinsic_name = intrinsic_name. as_str ( ) ;
@@ -48,32 +49,50 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
48
49
49
50
// All remaining supported intrinsics have a return place.
50
51
let ret = match ret {
52
+ // FIXME: add fallback body support once we actually have a diverging intrinsic with a fallback body
51
53
None => throw_unsup_format ! ( "unimplemented (diverging) intrinsic: `{intrinsic_name}`" ) ,
52
54
Some ( p) => p,
53
55
} ;
54
56
55
57
// Some intrinsics are special and need the "ret".
56
58
match intrinsic_name {
57
- "catch_unwind" => return this. handle_catch_unwind ( args, dest, ret) ,
59
+ "catch_unwind" => {
60
+ this. handle_catch_unwind ( args, dest, ret) ?;
61
+ return Ok ( None ) ;
62
+ }
58
63
_ => { }
59
64
}
60
65
61
66
// The rest jumps to `ret` immediately.
62
- this. emulate_intrinsic_by_name ( intrinsic_name, instance. args , args, dest) ?;
67
+ if !this. emulate_intrinsic_by_name ( intrinsic_name, instance. args , args, dest) ? {
68
+ // We haven't handled the intrinsic, let's see if we can use a fallback body.
69
+ if this. tcx . intrinsic ( instance. def_id ( ) ) . unwrap ( ) . must_be_overridden {
70
+ throw_unsup_format ! ( "unimplemented intrinsic: `{intrinsic_name}`" )
71
+ }
72
+ let intrinsic_fallback_checks_ub = Symbol :: intern ( "intrinsic_fallback_checks_ub" ) ;
73
+ if this. tcx . get_attrs_by_path ( instance. def_id ( ) , & [ sym:: miri, intrinsic_fallback_checks_ub] ) . next ( ) . is_none ( ) {
74
+ throw_unsup_format ! ( "miri can only use intrinsic fallback bodies that check UB. After verifying that `{intrinsic_name}` does so, add the `#[miri::intrinsic_fallback_checks_ub]` attribute to it; also ping @rust-lang/miri when you do that" ) ;
75
+ }
76
+ return Ok ( Some ( ty:: Instance {
77
+ def : ty:: InstanceDef :: Item ( instance. def_id ( ) ) ,
78
+ args : instance. args ,
79
+ } ) )
80
+ }
63
81
64
82
trace ! ( "{:?}" , this. dump_place( & dest. clone( ) . into( ) ) ) ;
65
83
this. go_to_block ( ret) ;
66
- Ok ( ( ) )
84
+ Ok ( None )
67
85
}
68
86
69
87
/// Emulates a Miri-supported intrinsic (not supported by the core engine).
88
+ /// Returns `Ok(true)` if the intrinsic was handled.
70
89
fn emulate_intrinsic_by_name (
71
90
& mut self ,
72
91
intrinsic_name : & str ,
73
92
generic_args : ty:: GenericArgsRef < ' tcx > ,
74
93
args : & [ OpTy < ' tcx , Provenance > ] ,
75
94
dest : & MPlaceTy < ' tcx , Provenance > ,
76
- ) -> InterpResult < ' tcx > {
95
+ ) -> InterpResult < ' tcx , bool > {
77
96
let this = self . eval_context_mut ( ) ;
78
97
79
98
if let Some ( name) = intrinsic_name. strip_prefix ( "atomic_" ) {
@@ -84,24 +103,6 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
84
103
}
85
104
86
105
match intrinsic_name {
87
- // Miri overwriting CTFE intrinsics.
88
- "ptr_guaranteed_cmp" => {
89
- let [ left, right] = check_arg_count ( args) ?;
90
- let left = this. read_immediate ( left) ?;
91
- let right = this. read_immediate ( right) ?;
92
- let val = this. wrapping_binary_op ( mir:: BinOp :: Eq , & left, & right) ?;
93
- // We're type punning a bool as an u8 here.
94
- this. write_scalar ( val. to_scalar ( ) , dest) ?;
95
- }
96
- "const_allocate" => {
97
- // For now, for compatibility with the run-time implementation of this, we just return null.
98
- // See <https://github.com/rust-lang/rust/issues/93935>.
99
- this. write_null ( dest) ?;
100
- }
101
- "const_deallocate" => {
102
- // complete NOP
103
- }
104
-
105
106
// Raw memory accesses
106
107
"volatile_load" => {
107
108
let [ place] = check_arg_count ( args) ?;
@@ -425,9 +426,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
425
426
throw_machine_stop ! ( TerminationInfo :: Abort ( format!( "trace/breakpoint trap" ) ) )
426
427
}
427
428
428
- name => throw_unsup_format ! ( "unimplemented intrinsic: `{name}`" ) ,
429
+ _ => return Ok ( false ) ,
429
430
}
430
431
431
- Ok ( ( ) )
432
+ Ok ( true )
432
433
}
433
434
}
0 commit comments