@@ -127,9 +127,31 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
127127 let tcx = & { this. tcx . tcx } ;
128128
129129 // First: functions that diverge.
130- let ( dest, ret) = match link_name {
131- // Note that this matches calls to the *foreign* item `__rust_start_panic* -
132- // that is, calls to `extern "Rust" { fn __rust_start_panic(...) }`.
130+ let ( dest, ret) = match ret {
131+ None => match link_name {
132+ // This matches calls to the foreign item `panic_impl`.
133+ // The implementation is provided by the function with the `#[panic_handler]` attribute.
134+ "panic_impl" => {
135+ let panic_impl_id = this. tcx . lang_items ( ) . panic_impl ( ) . unwrap ( ) ;
136+ let panic_impl_instance = ty:: Instance :: mono ( * this. tcx , panic_impl_id) ;
137+ return Ok ( Some ( & * this. load_mir ( panic_impl_instance. def , None ) ?) ) ;
138+ }
139+ | "exit"
140+ | "ExitProcess"
141+ => {
142+ // it's really u32 for ExitProcess, but we have to put it into the `Exit` variant anyway
143+ let code = this. read_scalar ( args[ 0 ] ) ?. to_i32 ( ) ?;
144+ throw_machine_stop ! ( TerminationInfo :: Exit ( code. into( ) ) ) ;
145+ }
146+ _ => throw_unsup_format ! ( "can't call (diverging) foreign function: {}" , link_name) ,
147+ } ,
148+ Some ( p) => p,
149+ } ;
150+
151+ // Second: some functions that we forward to MIR implementations.
152+ match link_name {
153+ // This matches calls to the *foreign* item `__rust_start_panic*, that is,
154+ // calls to `extern "Rust" { fn __rust_start_panic(...) }`.
133155 // We forward this to the underlying *implementation* in the panic runtime crate.
134156 // Normally, this will be either `libpanic_unwind` or `libpanic_abort`, but it could
135157 // also be a custom user-provided implementation via `#![feature(panic_runtime)]`
@@ -145,31 +167,10 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
145167 this. resolve_path ( & [ & * panic_runtime. as_str ( ) , "__rust_start_panic" ] ) ?;
146168 return Ok ( Some ( & * this. load_mir ( start_panic_instance. def , None ) ?) ) ;
147169 }
148- // Similarly, we forward calls to the `panic_impl` foreign item to its implementation.
149- // The implementation is provided by the function with the `#[panic_handler]` attribute.
150- "panic_impl" => {
151- let panic_impl_id = this. tcx . lang_items ( ) . panic_impl ( ) . unwrap ( ) ;
152- let panic_impl_instance = ty:: Instance :: mono ( * this. tcx , panic_impl_id) ;
153- return Ok ( Some ( & * this. load_mir ( panic_impl_instance. def , None ) ?) ) ;
154- }
155-
156- | "exit"
157- | "ExitProcess"
158- => {
159- // it's really u32 for ExitProcess, but we have to put it into the `Exit` variant anyway
160- let code = this. read_scalar ( args[ 0 ] ) ?. to_i32 ( ) ?;
161- throw_machine_stop ! ( TerminationInfo :: Exit ( code. into( ) ) ) ;
162- }
163- _ => {
164- if let Some ( p) = ret {
165- p
166- } else {
167- throw_unsup_format ! ( "can't call (diverging) foreign function: {}" , link_name) ;
168- }
169- }
170- } ;
170+ _ => { }
171+ }
171172
172- // Next : functions that return.
173+ // Third : functions that return.
173174 if this. emulate_foreign_item_by_name ( link_name, args, dest, ret) ? {
174175 this. dump_place ( * dest) ;
175176 this. go_to_block ( ret) ;
0 commit comments