Skip to content

Commit 97c2575

Browse files
committed
Auto merge of #1224 - RalfJung:diverge, r=RalfJung
refactor handling of diverging intrinsics/foreign functions Also makes sure we don't accidentally call some normal intrinsics diverging -- which it turns out we did.
2 parents 5b3d265 + 13ae314 commit 97c2575

File tree

2 files changed

+40
-40
lines changed

2 files changed

+40
-40
lines changed

src/shims/foreign_items.rs

Lines changed: 28 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -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);

src/shims/intrinsics.rs

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -31,22 +31,21 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
3131
// that might still hang around!
3232
let intrinsic_name = &*tcx.item_name(instance.def_id()).as_str();
3333

34-
// Handle diverging intrinsics.
35-
let (dest, ret) = match intrinsic_name {
36-
"abort" => {
37-
// FIXME: remove, once the intrinsic on the rustc side is fixed.
38-
throw_machine_stop!(TerminationInfo::Abort);
39-
}
40-
"miri_start_panic" => return this.handle_miri_start_panic(args, unwind),
41-
_ =>
42-
if let Some(p) = ret {
43-
p
44-
} else {
45-
throw_unsup_format!("unimplemented (diverging) intrinsic: {}", intrinsic_name);
46-
},
34+
// First handle intrinsics without return place.
35+
let (dest, ret) = match ret {
36+
None => match intrinsic_name {
37+
"abort" => {
38+
// FIXME: remove, once the intrinsic on the rustc side is fixed.
39+
throw_machine_stop!(TerminationInfo::Abort);
40+
}
41+
_ => throw_unsup_format!("unimplemented (diverging) intrinsic: {}", intrinsic_name),
42+
},
43+
Some(p) => p,
4744
};
4845

4946
match intrinsic_name {
47+
"miri_start_panic" => return this.handle_miri_start_panic(args, unwind),
48+
5049
"arith_offset" => {
5150
let offset = this.read_scalar(args[1])?.to_machine_isize(this)?;
5251
let ptr = this.read_scalar(args[0])?.not_undef()?;

0 commit comments

Comments
 (0)