From b07c1f7f4d46f083725a03f85a3c6cd3447267ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20du=20Garreau?= Date: Wed, 13 Mar 2024 15:09:39 +0100 Subject: [PATCH 1/6] Improve several `Read` implementations --- library/std/src/io/cursor.rs | 21 +++++++++++++++++++++ library/std/src/io/impls.rs | 4 +++- library/std/src/process.rs | 4 ++++ 3 files changed, 28 insertions(+), 1 deletion(-) diff --git a/library/std/src/io/cursor.rs b/library/std/src/io/cursor.rs index 49dde828c1f..c4e97fc45ff 100644 --- a/library/std/src/io/cursor.rs +++ b/library/std/src/io/cursor.rs @@ -364,6 +364,27 @@ where self.pos += n as u64; Ok(()) } + + fn read_to_end(&mut self, buf: &mut Vec) -> io::Result { + let content = self.remaining_slice(); + let len = content.len(); + buf.try_reserve(len)?; + buf.extend_from_slice(content); + self.pos += len as u64; + + Ok(len) + } + + fn read_to_string(&mut self, buf: &mut String) -> io::Result { + let content = + crate::str::from_utf8(self.remaining_slice()).map_err(|_| io::Error::INVALID_UTF8)?; + let len = content.len(); + buf.try_reserve(len)?; + buf.push_str(content); + self.pos += len as u64; + + Ok(len) + } } #[stable(feature = "rust1", since = "1.0.0")] diff --git a/library/std/src/io/impls.rs b/library/std/src/io/impls.rs index dd7e0725176..9f9ee4af5c8 100644 --- a/library/std/src/io/impls.rs +++ b/library/std/src/io/impls.rs @@ -329,8 +329,9 @@ impl Read for &[u8] { #[inline] fn read_to_string(&mut self, buf: &mut String) -> io::Result { let content = str::from_utf8(self).map_err(|_| io::Error::INVALID_UTF8)?; - buf.push_str(content); let len = self.len(); + buf.try_reserve(len)?; + buf.push_str(content); *self = &self[len..]; Ok(len) } @@ -478,6 +479,7 @@ impl Read for VecDeque { let len = self.len(); let content = self.make_contiguous(); let string = str::from_utf8(content).map_err(|_| io::Error::INVALID_UTF8)?; + buf.try_reserve(len)?; buf.push_str(string); self.clear(); Ok(len) diff --git a/library/std/src/process.rs b/library/std/src/process.rs index 69cc61b30ef..ab282135d1a 100644 --- a/library/std/src/process.rs +++ b/library/std/src/process.rs @@ -486,6 +486,10 @@ impl Read for ChildStderr { fn is_read_vectored(&self) -> bool { self.inner.is_read_vectored() } + + fn read_to_end(&mut self, buf: &mut Vec) -> io::Result { + self.inner.read_to_end(buf) + } } impl AsInner for ChildStderr { From 23211b638a78bc7b3e69b8e8cdd25abebeb0f7ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20du=20Garreau?= Date: Thu, 14 Mar 2024 11:20:59 +0100 Subject: [PATCH 2/6] `VecDeque::read_to_string`: avoid making the slices contiguous --- library/std/src/io/impls.rs | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/library/std/src/io/impls.rs b/library/std/src/io/impls.rs index 9f9ee4af5c8..46f04c7cd39 100644 --- a/library/std/src/io/impls.rs +++ b/library/std/src/io/impls.rs @@ -474,15 +474,8 @@ impl Read for VecDeque { #[inline] fn read_to_string(&mut self, buf: &mut String) -> io::Result { - // We have to use a single contiguous slice because the `VecDequeue` might be split in the - // middle of an UTF-8 character. - let len = self.len(); - let content = self.make_contiguous(); - let string = str::from_utf8(content).map_err(|_| io::Error::INVALID_UTF8)?; - buf.try_reserve(len)?; - buf.push_str(string); - self.clear(); - Ok(len) + // SAFETY: We only append to the buffer + unsafe { io::append_to_string(buf, |buf| self.read_to_end(buf)) } } } From 2e3ee230220cc81b159d99d833cba46c667e3321 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20du=20Garreau?= Date: Wed, 10 Apr 2024 19:16:31 +0200 Subject: [PATCH 3/6] Avoid panicking branch in `append_to_string` --- library/std/src/io/mod.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs index 98973a43e1d..450fa43ebea 100644 --- a/library/std/src/io/mod.rs +++ b/library/std/src/io/mod.rs @@ -384,7 +384,10 @@ where { let mut g = Guard { len: buf.len(), buf: buf.as_mut_vec() }; let ret = f(g.buf); - if str::from_utf8(&g.buf[g.len..]).is_err() { + + // SAFETY: the caller promises to only append data to `buf` + let appended = g.buf.get_unchecked(g.len..); + if str::from_utf8(appended).is_err() { ret.and_then(|_| Err(Error::INVALID_UTF8)) } else { g.len = g.buf.len(); From f1de4c16ee3dae0599efa64d6ebe601efbe23769 Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Sat, 4 May 2024 00:54:21 -0700 Subject: [PATCH 4/6] Use `unchecked_sub` in `split_at` --- library/core/src/slice/mod.rs | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index 6e1ba74f72b..6e6d66f0aae 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -9,7 +9,7 @@ use crate::cmp::Ordering::{self, Equal, Greater, Less}; use crate::fmt; use crate::hint; -use crate::intrinsics::exact_div; +use crate::intrinsics::{exact_div, unchecked_sub}; use crate::mem::{self, SizedTypeProperties}; use crate::num::NonZero; use crate::ops::{Bound, OneSidedRange, Range, RangeBounds}; @@ -1983,7 +1983,7 @@ impl [T] { ); // SAFETY: Caller has to check that `0 <= mid <= self.len()` - unsafe { (from_raw_parts(ptr, mid), from_raw_parts(ptr.add(mid), len - mid)) } + unsafe { (from_raw_parts(ptr, mid), from_raw_parts(ptr.add(mid), unchecked_sub(len, mid))) } } /// Divides one mutable slice into two at an index, without doing bounds checking. @@ -2035,7 +2035,12 @@ impl [T] { // // `[ptr; mid]` and `[mid; len]` are not overlapping, so returning a mutable reference // is fine. - unsafe { (from_raw_parts_mut(ptr, mid), from_raw_parts_mut(ptr.add(mid), len - mid)) } + unsafe { + ( + from_raw_parts_mut(ptr, mid), + from_raw_parts_mut(ptr.add(mid), unchecked_sub(len, mid)), + ) + } } /// Divides one slice into two at an index, returning `None` if the slice is From 1572c0dcd7b5d9e4fcd400d3b34f1d675201f150 Mon Sep 17 00:00:00 2001 From: Nilstrieb <48135649+Nilstrieb@users.noreply.github.com> Date: Wed, 1 May 2024 17:37:22 +0200 Subject: [PATCH 5/6] Various improvements to entrypoint code This moves some code around and adds some documentation comments to make it easier to understand what's going on with the entrypoint logic, which is a bit complicated. The only change in behavior is consolidating the error messages for unix_sigpipe to make the code slightly simpler. --- compiler/rustc_ast/src/entry.rs | 26 +++++++++++- .../rustc_builtin_macros/src/test_harness.rs | 2 +- compiler/rustc_passes/messages.ftl | 6 --- compiler/rustc_passes/src/entry.rs | 42 ++++++++++--------- compiler/rustc_passes/src/errors.rs | 16 ------- 5 files changed, 49 insertions(+), 43 deletions(-) diff --git a/compiler/rustc_ast/src/entry.rs b/compiler/rustc_ast/src/entry.rs index cd8a5a66920..dd231e286d5 100644 --- a/compiler/rustc_ast/src/entry.rs +++ b/compiler/rustc_ast/src/entry.rs @@ -4,11 +4,35 @@ use rustc_span::Symbol; #[derive(Debug)] pub enum EntryPointType { + /// This function is not an entrypoint. None, + /// This is a function called `main` at the root level. + /// ``` + /// fn main() {} + /// ``` MainNamed, + /// This is a function with the `#[rustc_main]` attribute. + /// Used by the testing harness to create the test entrypoint. + /// ```ignore (clashes with test entrypoint) + /// #[rustc_main] + /// fn main() {} + /// ``` RustcMainAttr, + /// This is a function with the `#[start]` attribute. + /// ```ignore (clashes with test entrypoint) + /// #[start] + /// fn main() {} + /// ``` Start, - OtherMain, // Not an entry point, but some other function named main + /// This function is **not** an entrypoint but simply named `main` (not at the root). + /// This is only used for diagnostics. + /// ``` + /// #[allow(dead_code)] + /// mod meow { + /// fn main() {} + /// } + /// ``` + OtherMain, } pub fn entry_point_type( diff --git a/compiler/rustc_builtin_macros/src/test_harness.rs b/compiler/rustc_builtin_macros/src/test_harness.rs index a2015445b42..8cf431482ff 100644 --- a/compiler/rustc_builtin_macros/src/test_harness.rs +++ b/compiler/rustc_builtin_macros/src/test_harness.rs @@ -266,7 +266,7 @@ fn generate_test_harness( /// /// By default this expands to /// -/// ```ignore UNSOLVED (I think I still need guidance for this one. Is it correct? Do we try to make it run? How do we nicely fill it out?) +/// ```ignore (messes with test internals) /// #[rustc_main] /// pub fn main() { /// extern crate test; diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl index 8878310d6e9..9d58d301e2b 100644 --- a/compiler/rustc_passes/messages.ftl +++ b/compiler/rustc_passes/messages.ftl @@ -49,12 +49,6 @@ passes_attr_crate_level = passes_attr_only_in_functions = `{$attr}` attribute can only be used on functions -passes_attr_only_on_main = - `{$attr}` attribute can only be used on `fn main()` - -passes_attr_only_on_root_main = - `{$attr}` attribute can only be used on root `fn main()` - passes_both_ffi_const_and_pure = `#[ffi_const]` function cannot be `#[ffi_pure]` diff --git a/compiler/rustc_passes/src/entry.rs b/compiler/rustc_passes/src/entry.rs index d52092f2aa9..b43c8282db1 100644 --- a/compiler/rustc_passes/src/entry.rs +++ b/compiler/rustc_passes/src/entry.rs @@ -18,10 +18,10 @@ use crate::errors::{ struct EntryContext<'tcx> { tcx: TyCtxt<'tcx>, - /// The function that has attribute named `main`. - attr_main_fn: Option<(LocalDefId, Span)>, + /// The function has the `#[rustc_main]` attribute. + rustc_main_fn: Option<(LocalDefId, Span)>, - /// The function that has the attribute 'start' on it. + /// The function that has the attribute `#[start]` on it. start_fn: Option<(LocalDefId, Span)>, /// The functions that one might think are `main` but aren't, e.g. @@ -42,10 +42,10 @@ fn entry_fn(tcx: TyCtxt<'_>, (): ()) -> Option<(DefId, EntryFnType)> { } let mut ctxt = - EntryContext { tcx, attr_main_fn: None, start_fn: None, non_main_fns: Vec::new() }; + EntryContext { tcx, rustc_main_fn: None, start_fn: None, non_main_fns: Vec::new() }; for id in tcx.hir().items() { - find_item(id, &mut ctxt); + check_and_search_item(id, &mut ctxt); } configure_main(tcx, &ctxt) @@ -56,7 +56,16 @@ fn attr_span_by_symbol(ctxt: &EntryContext<'_>, id: ItemId, sym: Symbol) -> Opti attr::find_by_name(attrs, sym).map(|attr| attr.span) } -fn find_item(id: ItemId, ctxt: &mut EntryContext<'_>) { +fn check_and_search_item(id: ItemId, ctxt: &mut EntryContext<'_>) { + if !matches!(ctxt.tcx.def_kind(id.owner_id), DefKind::Fn) { + for attr in [sym::start, sym::rustc_main] { + if let Some(span) = attr_span_by_symbol(ctxt, id, attr) { + ctxt.tcx.dcx().emit_err(AttrOnlyInFunctions { span, attr }); + } + } + return; + } + let at_root = ctxt.tcx.opt_local_parent(id.owner_id.def_id) == Some(CRATE_DEF_ID); let attrs = ctxt.tcx.hir().attrs(id.hir_id()); @@ -65,26 +74,20 @@ fn find_item(id: ItemId, ctxt: &mut EntryContext<'_>) { at_root, ctxt.tcx.opt_item_name(id.owner_id.to_def_id()), ); + match entry_point_type { - EntryPointType::None => (), - _ if !matches!(ctxt.tcx.def_kind(id.owner_id), DefKind::Fn) => { - for attr in [sym::start, sym::rustc_main] { - if let Some(span) = attr_span_by_symbol(ctxt, id, attr) { - ctxt.tcx.dcx().emit_err(AttrOnlyInFunctions { span, attr }); - } - } - } - EntryPointType::MainNamed => (), + EntryPointType::None => {} + EntryPointType::MainNamed => {} EntryPointType::OtherMain => { ctxt.non_main_fns.push(ctxt.tcx.def_span(id.owner_id)); } EntryPointType::RustcMainAttr => { - if ctxt.attr_main_fn.is_none() { - ctxt.attr_main_fn = Some((id.owner_id.def_id, ctxt.tcx.def_span(id.owner_id))); + if ctxt.rustc_main_fn.is_none() { + ctxt.rustc_main_fn = Some((id.owner_id.def_id, ctxt.tcx.def_span(id.owner_id))); } else { ctxt.tcx.dcx().emit_err(MultipleRustcMain { span: ctxt.tcx.def_span(id.owner_id.to_def_id()), - first: ctxt.attr_main_fn.unwrap().1, + first: ctxt.rustc_main_fn.unwrap().1, additional: ctxt.tcx.def_span(id.owner_id.to_def_id()), }); } @@ -107,10 +110,11 @@ fn find_item(id: ItemId, ctxt: &mut EntryContext<'_>) { fn configure_main(tcx: TyCtxt<'_>, visitor: &EntryContext<'_>) -> Option<(DefId, EntryFnType)> { if let Some((def_id, _)) = visitor.start_fn { Some((def_id.to_def_id(), EntryFnType::Start)) - } else if let Some((local_def_id, _)) = visitor.attr_main_fn { + } else if let Some((local_def_id, _)) = visitor.rustc_main_fn { let def_id = local_def_id.to_def_id(); Some((def_id, EntryFnType::Main { sigpipe: sigpipe(tcx) })) } else { + // The actual resolution of main happens in the resolver, this here if let Some(main_def) = tcx.resolutions(()).main_def && let Some(def_id) = main_def.opt_fn_def_id() { diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs index 743faf54560..65cad82cc8c 100644 --- a/compiler/rustc_passes/src/errors.rs +++ b/compiler/rustc_passes/src/errors.rs @@ -1206,22 +1206,6 @@ pub struct NakedFunctionsMustUseNoreturn { pub last_span: Span, } -#[derive(Diagnostic)] -#[diag(passes_attr_only_on_main)] -pub struct AttrOnlyOnMain { - #[primary_span] - pub span: Span, - pub attr: Symbol, -} - -#[derive(Diagnostic)] -#[diag(passes_attr_only_on_root_main)] -pub struct AttrOnlyOnRootMain { - #[primary_span] - pub span: Span, - pub attr: Symbol, -} - #[derive(Diagnostic)] #[diag(passes_attr_only_in_functions)] pub struct AttrOnlyInFunctions { From 8e4466497fb8f5c1d87535cfe0c2d154b152ab9e Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 4 May 2024 17:39:29 +0200 Subject: [PATCH 6/6] interpret, miri: uniform treatments of intrinsics/functions with and without return block --- .../src/const_eval/machine.rs | 16 +- .../src/interpret/intrinsics.rs | 9 +- src/tools/miri/src/lib.rs | 1 + src/tools/miri/src/shims/alloc.rs | 9 +- src/tools/miri/src/shims/foreign_items.rs | 170 ++++++++---------- src/tools/miri/src/shims/intrinsics/atomic.rs | 6 +- src/tools/miri/src/shims/intrinsics/mod.rs | 93 +++++----- src/tools/miri/src/shims/intrinsics/simd.rs | 6 +- src/tools/miri/src/shims/mod.rs | 10 ++ src/tools/miri/src/shims/panic.rs | 8 +- .../miri/src/shims/unix/foreign_items.rs | 7 +- .../src/shims/unix/freebsd/foreign_items.rs | 7 +- .../src/shims/unix/linux/foreign_items.rs | 9 +- .../src/shims/unix/macos/foreign_items.rs | 7 +- .../miri/src/shims/windows/foreign_items.rs | 7 +- src/tools/miri/src/shims/x86/aesni.rs | 7 +- src/tools/miri/src/shims/x86/avx.rs | 7 +- src/tools/miri/src/shims/x86/avx2.rs | 7 +- src/tools/miri/src/shims/x86/mod.rs | 11 +- src/tools/miri/src/shims/x86/sse.rs | 7 +- src/tools/miri/src/shims/x86/sse2.rs | 7 +- src/tools/miri/src/shims/x86/sse3.rs | 7 +- src/tools/miri/src/shims/x86/sse41.rs | 7 +- src/tools/miri/src/shims/x86/ssse3.rs | 7 +- 24 files changed, 192 insertions(+), 240 deletions(-) diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs index e9cf5a3d769..6e6fa70107b 100644 --- a/compiler/rustc_const_eval/src/const_eval/machine.rs +++ b/compiler/rustc_const_eval/src/const_eval/machine.rs @@ -467,19 +467,6 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir, let intrinsic_name = ecx.tcx.item_name(instance.def_id()); // CTFE-specific intrinsics. - let Some(ret) = target else { - // Handle diverging intrinsics. We can't handle any of them (that are not already - // handled above), but check if there is a fallback body. - if ecx.tcx.intrinsic(instance.def_id()).unwrap().must_be_overridden { - throw_unsup_format!( - "intrinsic `{intrinsic_name}` is not supported at compile-time" - ); - } - return Ok(Some(ty::Instance { - def: ty::InstanceDef::Item(instance.def_id()), - args: instance.args, - })); - }; match intrinsic_name { sym::ptr_guaranteed_cmp => { let a = ecx.read_scalar(&args[0])?; @@ -559,7 +546,8 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir, } } - ecx.go_to_block(ret); + // Intrinsic is done, jump to next block. + ecx.return_to_block(target)?; Ok(None) } diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics.rs b/compiler/rustc_const_eval/src/interpret/intrinsics.rs index f73293856c7..88ce5a7cbeb 100644 --- a/compiler/rustc_const_eval/src/interpret/intrinsics.rs +++ b/compiler/rustc_const_eval/src/interpret/intrinsics.rs @@ -113,10 +113,6 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { ) -> InterpResult<'tcx, bool> { let instance_args = instance.args; let intrinsic_name = self.tcx.item_name(instance.def_id()); - let Some(ret) = ret else { - // We don't support any intrinsic without return place. - return Ok(false); - }; match intrinsic_name { sym::caller_location => { @@ -376,7 +372,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { }; M::panic_nounwind(self, &msg)?; - // Skip the `go_to_block` at the end. + // Skip the `return_to_block` at the end (we panicked, we do not return). return Ok(true); } } @@ -437,11 +433,12 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { self.write_scalar(Scalar::from_target_usize(align.bytes(), self), dest)?; } + // Unsupported intrinsic: skip the return_to_block below. _ => return Ok(false), } trace!("{:?}", self.dump_place(&dest.clone().into())); - self.go_to_block(ret); + self.return_to_block(ret)?; Ok(true) } diff --git a/src/tools/miri/src/lib.rs b/src/tools/miri/src/lib.rs index f47c84842b1..3b1d7687d02 100644 --- a/src/tools/miri/src/lib.rs +++ b/src/tools/miri/src/lib.rs @@ -95,6 +95,7 @@ pub use rustc_const_eval::interpret::*; #[doc(no_inline)] pub use rustc_const_eval::interpret::{self, AllocMap, PlaceTy, Provenance as _}; +pub use crate::shims::EmulateItemResult; pub use crate::shims::env::{EnvVars, EvalContextExt as _}; pub use crate::shims::foreign_items::{DynSym, EvalContextExt as _}; pub use crate::shims::intrinsics::EvalContextExt as _; diff --git a/src/tools/miri/src/shims/alloc.rs b/src/tools/miri/src/shims/alloc.rs index b5ae06c2a49..79531598c00 100644 --- a/src/tools/miri/src/shims/alloc.rs +++ b/src/tools/miri/src/shims/alloc.rs @@ -4,7 +4,6 @@ use rustc_ast::expand::allocator::AllocatorKind; use rustc_target::abi::{Align, Size}; use crate::*; -use shims::foreign_items::EmulateForeignItemResult; /// Check some basic requirements for this allocation request: /// non-zero size, power-of-two alignment. @@ -55,12 +54,12 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { fn emulate_allocator( &mut self, default: impl FnOnce(&mut MiriInterpCx<'mir, 'tcx>) -> InterpResult<'tcx>, - ) -> InterpResult<'tcx, EmulateForeignItemResult> { + ) -> InterpResult<'tcx, EmulateItemResult> { let this = self.eval_context_mut(); let Some(allocator_kind) = this.tcx.allocator_kind(()) else { // in real code, this symbol does not exist without an allocator - return Ok(EmulateForeignItemResult::NotSupported); + return Ok(EmulateItemResult::NotSupported); }; match allocator_kind { @@ -70,11 +69,11 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { // and not execute any Miri shim. Somewhat unintuitively doing so is done // by returning `NotSupported`, which triggers the `lookup_exported_symbol` // fallback case in `emulate_foreign_item`. - return Ok(EmulateForeignItemResult::NotSupported); + return Ok(EmulateItemResult::NotSupported); } AllocatorKind::Default => { default(this)?; - Ok(EmulateForeignItemResult::NeedsJumping) + Ok(EmulateItemResult::NeedsJumping) } } } diff --git a/src/tools/miri/src/shims/foreign_items.rs b/src/tools/miri/src/shims/foreign_items.rs index 636361148a4..8a38c6c11a8 100644 --- a/src/tools/miri/src/shims/foreign_items.rs +++ b/src/tools/miri/src/shims/foreign_items.rs @@ -28,16 +28,6 @@ impl DynSym { } } -/// Returned by `emulate_foreign_item_inner`. -pub enum EmulateForeignItemResult { - /// The caller is expected to jump to the return block. - NeedsJumping, - /// Jumping has already been taken care of. - AlreadyJumped, - /// The item is not supported. - NotSupported, -} - impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {} pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { /// Emulates calling a foreign item, failing if the item is not supported. @@ -58,84 +48,47 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let this = self.eval_context_mut(); let tcx = this.tcx.tcx; - // First: functions that diverge. - let ret = match ret { - None => - match link_name.as_str() { - "miri_start_unwind" => { - // `check_shim` happens inside `handle_miri_start_unwind`. - this.handle_miri_start_unwind(abi, link_name, args, unwind)?; - return Ok(None); - } - // This matches calls to the foreign item `panic_impl`. - // The implementation is provided by the function with the `#[panic_handler]` attribute. - "panic_impl" => { - // We don't use `check_shim` here because we are just forwarding to the lang - // item. Argument count checking will be performed when the returned `Body` is - // called. - this.check_abi_and_shim_symbol_clash(abi, Abi::Rust, link_name)?; - let panic_impl_id = tcx.lang_items().panic_impl().unwrap(); - let panic_impl_instance = ty::Instance::mono(tcx, panic_impl_id); - return Ok(Some(( - this.load_mir(panic_impl_instance.def, None)?, - panic_impl_instance, - ))); - } - "__rust_alloc_error_handler" => { - // Forward to the right symbol that implements this function. - let Some(handler_kind) = this.tcx.alloc_error_handler_kind(()) else { - // in real code, this symbol does not exist without an allocator - throw_unsup_format!( - "`__rust_alloc_error_handler` cannot be called when no alloc error handler is set" - ); - }; - let name = alloc_error_handler_name(handler_kind); - let handler = this - .lookup_exported_symbol(Symbol::intern(name))? - .expect("missing alloc error handler symbol"); - return Ok(Some(handler)); - } - #[rustfmt::skip] - | "exit" - | "ExitProcess" - => { - let exp_abi = if link_name.as_str() == "exit" { - Abi::C { unwind: false } - } else { - Abi::System { unwind: false } - }; - let [code] = this.check_shim(abi, exp_abi, link_name, args)?; - // it's really u32 for ExitProcess, but we have to put it into the `Exit` variant anyway - let code = this.read_scalar(code)?.to_i32()?; - throw_machine_stop!(TerminationInfo::Exit { code: code.into(), leak_check: false }); - } - "abort" => { - let [] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; - throw_machine_stop!(TerminationInfo::Abort( - "the program aborted execution".to_owned() - )) - } - _ => { - if let Some(body) = this.lookup_exported_symbol(link_name)? { - return Ok(Some(body)); - } - this.handle_unsupported(format!( - "can't call (diverging) foreign function: {link_name}" - ))?; - return Ok(None); - } - }, - Some(p) => p, - }; - - // Second: functions that return immediately. - match this.emulate_foreign_item_inner(link_name, abi, args, dest)? { - EmulateForeignItemResult::NeedsJumping => { - trace!("{:?}", this.dump_place(&dest.clone().into())); - this.go_to_block(ret); + // Some shims forward to other MIR bodies. + match link_name.as_str() { + // This matches calls to the foreign item `panic_impl`. + // The implementation is provided by the function with the `#[panic_handler]` attribute. + "panic_impl" => { + // We don't use `check_shim` here because we are just forwarding to the lang + // item. Argument count checking will be performed when the returned `Body` is + // called. + this.check_abi_and_shim_symbol_clash(abi, Abi::Rust, link_name)?; + let panic_impl_id = tcx.lang_items().panic_impl().unwrap(); + let panic_impl_instance = ty::Instance::mono(tcx, panic_impl_id); + return Ok(Some(( + this.load_mir(panic_impl_instance.def, None)?, + panic_impl_instance, + ))); } - EmulateForeignItemResult::AlreadyJumped => (), - EmulateForeignItemResult::NotSupported => { + "__rust_alloc_error_handler" => { + // Forward to the right symbol that implements this function. + let Some(handler_kind) = this.tcx.alloc_error_handler_kind(()) else { + // in real code, this symbol does not exist without an allocator + throw_unsup_format!( + "`__rust_alloc_error_handler` cannot be called when no alloc error handler is set" + ); + }; + let name = alloc_error_handler_name(handler_kind); + let handler = this + .lookup_exported_symbol(Symbol::intern(name))? + .expect("missing alloc error handler symbol"); + return Ok(Some(handler)); + } + _ => {} + } + + // The rest either implements the logic, or falls back to `lookup_exported_symbol`. + match this.emulate_foreign_item_inner(link_name, abi, args, dest, unwind)? { + EmulateItemResult::NeedsJumping => { + trace!("{:?}", this.dump_place(&dest.clone().into())); + this.return_to_block(ret)?; + } + EmulateItemResult::AlreadyJumped => (), + EmulateItemResult::NotSupported => { if let Some(body) = this.lookup_exported_symbol(link_name)? { return Ok(Some(body)); } @@ -243,7 +196,8 @@ trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { abi: Abi, args: &[OpTy<'tcx, Provenance>], dest: &MPlaceTy<'tcx, Provenance>, - ) -> InterpResult<'tcx, EmulateForeignItemResult> { + unwind: mir::UnwindAction, + ) -> InterpResult<'tcx, EmulateItemResult> { let this = self.eval_context_mut(); // First deal with any external C functions in linked .so file. @@ -254,7 +208,7 @@ trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { // by the specified `.so` file; we should continue and check if it corresponds to // a provided shim. if this.call_external_c_fct(link_name, dest, args)? { - return Ok(EmulateForeignItemResult::NeedsJumping); + return Ok(EmulateItemResult::NeedsJumping); } } @@ -298,6 +252,11 @@ trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { // shim, add it to the corresponding submodule. match link_name.as_str() { // Miri-specific extern functions + "miri_start_unwind" => { + // `check_shim` happens inside `handle_miri_start_unwind`. + this.handle_miri_start_unwind(abi, link_name, args, unwind)?; + return Ok(EmulateItemResult::AlreadyJumped); + } "miri_run_provenance_gc" => { let [] = this.check_shim(abi, Abi::Rust, link_name, args)?; this.run_provenance_gc(); @@ -362,29 +321,24 @@ trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { // Return value: 0 on success, otherwise the size it would have needed. this.write_int(if success { 0 } else { needed_size }, dest)?; } - // Obtains the size of a Miri backtrace. See the README for details. "miri_backtrace_size" => { this.handle_miri_backtrace_size(abi, link_name, args, dest)?; } - // Obtains a Miri backtrace. See the README for details. "miri_get_backtrace" => { // `check_shim` happens inside `handle_miri_get_backtrace`. this.handle_miri_get_backtrace(abi, link_name, args, dest)?; } - // Resolves a Miri backtrace frame. See the README for details. "miri_resolve_frame" => { // `check_shim` happens inside `handle_miri_resolve_frame`. this.handle_miri_resolve_frame(abi, link_name, args, dest)?; } - // Writes the function and file names of a Miri backtrace frame into a user provided buffer. See the README for details. "miri_resolve_frame_names" => { this.handle_miri_resolve_frame_names(abi, link_name, args)?; } - // Writes some bytes to the interpreter's stdout/stderr. See the // README for details. "miri_write_to_stdout" | "miri_write_to_stderr" => { @@ -398,7 +352,6 @@ trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { _ => unreachable!(), }; } - // Promises that a pointer has a given symbolic alignment. "miri_promise_symbolic_alignment" => { use rustc_target::abi::AlignFromBytesError; @@ -442,6 +395,25 @@ trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { } } + // Aborting the process. + "exit" | "ExitProcess" => { + let exp_abi = if link_name.as_str() == "exit" { + Abi::C { unwind: false } + } else { + Abi::System { unwind: false } + }; + let [code] = this.check_shim(abi, exp_abi, link_name, args)?; + // it's really u32 for ExitProcess, but we have to put it into the `Exit` variant anyway + let code = this.read_scalar(code)?.to_i32()?; + throw_machine_stop!(TerminationInfo::Exit { code: code.into(), leak_check: false }); + } + "abort" => { + let [] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; + throw_machine_stop!(TerminationInfo::Abort( + "the program aborted execution".to_owned() + )) + } + // Standard C allocation "malloc" => { let [size] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; @@ -504,7 +476,7 @@ trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { "__rust_alloc" => return this.emulate_allocator(default), "miri_alloc" => { default(this)?; - return Ok(EmulateForeignItemResult::NeedsJumping); + return Ok(EmulateItemResult::NeedsJumping); } _ => unreachable!(), } @@ -564,7 +536,7 @@ trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { } "miri_dealloc" => { default(this)?; - return Ok(EmulateForeignItemResult::NeedsJumping); + return Ok(EmulateItemResult::NeedsJumping); } _ => unreachable!(), } @@ -966,11 +938,11 @@ trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { shims::windows::foreign_items::EvalContextExt::emulate_foreign_item_inner( this, link_name, abi, args, dest, ), - _ => Ok(EmulateForeignItemResult::NotSupported), + _ => Ok(EmulateItemResult::NotSupported), }, }; // We only fall through to here if we did *not* hit the `_` arm above, // i.e., if we actually emulated the function with one of the shims. - Ok(EmulateForeignItemResult::NeedsJumping) + Ok(EmulateItemResult::NeedsJumping) } } diff --git a/src/tools/miri/src/shims/intrinsics/atomic.rs b/src/tools/miri/src/shims/intrinsics/atomic.rs index 4c5e2192e5c..40f6b8a64ef 100644 --- a/src/tools/miri/src/shims/intrinsics/atomic.rs +++ b/src/tools/miri/src/shims/intrinsics/atomic.rs @@ -20,7 +20,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { intrinsic_name: &str, args: &[OpTy<'tcx, Provenance>], dest: &MPlaceTy<'tcx, Provenance>, - ) -> InterpResult<'tcx, bool> { + ) -> InterpResult<'tcx, EmulateItemResult> { let this = self.eval_context_mut(); let intrinsic_structure: Vec<_> = intrinsic_name.split('_').collect(); @@ -114,9 +114,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { this.atomic_rmw_op(args, dest, AtomicOp::Max, rw_ord(ord)?)?; } - _ => return Ok(false), + _ => return Ok(EmulateItemResult::NotSupported), } - Ok(true) + Ok(EmulateItemResult::NeedsJumping) } } diff --git a/src/tools/miri/src/shims/intrinsics/mod.rs b/src/tools/miri/src/shims/intrinsics/mod.rs index 2bf6980200f..974943432aa 100644 --- a/src/tools/miri/src/shims/intrinsics/mod.rs +++ b/src/tools/miri/src/shims/intrinsics/mod.rs @@ -10,8 +10,8 @@ use rustc_middle::{ mir, ty::{self, FloatTy}, }; -use rustc_target::abi::Size; use rustc_span::{sym, Symbol}; +use rustc_target::abi::Size; use crate::*; use atomic::EvalContextExt as _; @@ -37,51 +37,38 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let intrinsic_name = this.tcx.item_name(instance.def_id()); let intrinsic_name = intrinsic_name.as_str(); - // Handle intrinsics without return place. - match intrinsic_name { - "abort" => { - throw_machine_stop!(TerminationInfo::Abort( - "the program aborted execution".to_owned() - )) + match this.emulate_intrinsic_by_name(intrinsic_name, instance.args, args, dest, ret)? { + EmulateItemResult::NotSupported => { + // We haven't handled the intrinsic, let's see if we can use a fallback body. + if this.tcx.intrinsic(instance.def_id()).unwrap().must_be_overridden { + throw_unsup_format!("unimplemented intrinsic: `{intrinsic_name}`") + } + let intrinsic_fallback_checks_ub = Symbol::intern("intrinsic_fallback_checks_ub"); + if this + .tcx + .get_attrs_by_path( + instance.def_id(), + &[sym::miri, intrinsic_fallback_checks_ub], + ) + .next() + .is_none() + { + 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" + ); + } + Ok(Some(ty::Instance { + def: ty::InstanceDef::Item(instance.def_id()), + args: instance.args, + })) } - _ => {} + EmulateItemResult::NeedsJumping => { + trace!("{:?}", this.dump_place(&dest.clone().into())); + this.return_to_block(ret)?; + Ok(None) + } + EmulateItemResult::AlreadyJumped => Ok(None), } - - // All remaining supported intrinsics have a return place. - let ret = match ret { - // FIXME: add fallback body support once we actually have a diverging intrinsic with a fallback body - None => throw_unsup_format!("unimplemented (diverging) intrinsic: `{intrinsic_name}`"), - Some(p) => p, - }; - - // Some intrinsics are special and need the "ret". - match intrinsic_name { - "catch_unwind" => { - this.handle_catch_unwind(args, dest, ret)?; - return Ok(None); - } - _ => {} - } - - // The rest jumps to `ret` immediately. - if !this.emulate_intrinsic_by_name(intrinsic_name, instance.args, args, dest)? { - // We haven't handled the intrinsic, let's see if we can use a fallback body. - if this.tcx.intrinsic(instance.def_id()).unwrap().must_be_overridden { - throw_unsup_format!("unimplemented intrinsic: `{intrinsic_name}`") - } - let intrinsic_fallback_checks_ub = Symbol::intern("intrinsic_fallback_checks_ub"); - if this.tcx.get_attrs_by_path(instance.def_id(), &[sym::miri, intrinsic_fallback_checks_ub]).next().is_none() { - 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"); - } - return Ok(Some(ty::Instance { - def: ty::InstanceDef::Item(instance.def_id()), - args: instance.args, - })) - } - - trace!("{:?}", this.dump_place(&dest.clone().into())); - this.go_to_block(ret); - Ok(None) } /// Emulates a Miri-supported intrinsic (not supported by the core engine). @@ -92,7 +79,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { generic_args: ty::GenericArgsRef<'tcx>, args: &[OpTy<'tcx, Provenance>], dest: &MPlaceTy<'tcx, Provenance>, - ) -> InterpResult<'tcx, bool> { + ret: Option, + ) -> InterpResult<'tcx, EmulateItemResult> { let this = self.eval_context_mut(); if let Some(name) = intrinsic_name.strip_prefix("atomic_") { @@ -103,6 +91,17 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { } match intrinsic_name { + "abort" => { + throw_machine_stop!(TerminationInfo::Abort( + "the program aborted execution".to_owned() + )); + } + "catch_unwind" => { + this.handle_catch_unwind(args, dest, ret)?; + // THis pushed a stack frame, don't jump to `ret`. + return Ok(EmulateItemResult::AlreadyJumped); + } + // Raw memory accesses "volatile_load" => { let [place] = check_arg_count(args)?; @@ -426,9 +425,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { throw_machine_stop!(TerminationInfo::Abort(format!("trace/breakpoint trap"))) } - _ => return Ok(false), + _ => return Ok(EmulateItemResult::NotSupported), } - Ok(true) + Ok(EmulateItemResult::NeedsJumping) } } diff --git a/src/tools/miri/src/shims/intrinsics/simd.rs b/src/tools/miri/src/shims/intrinsics/simd.rs index dca4c4ea5ad..c7de587443a 100644 --- a/src/tools/miri/src/shims/intrinsics/simd.rs +++ b/src/tools/miri/src/shims/intrinsics/simd.rs @@ -23,7 +23,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { generic_args: ty::GenericArgsRef<'tcx>, args: &[OpTy<'tcx, Provenance>], dest: &MPlaceTy<'tcx, Provenance>, - ) -> InterpResult<'tcx, bool> { + ) -> InterpResult<'tcx, EmulateItemResult> { let this = self.eval_context_mut(); match intrinsic_name { #[rustfmt::skip] @@ -744,9 +744,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { } } - _ => return Ok(false), + _ => return Ok(EmulateItemResult::NotSupported), } - Ok(true) + Ok(EmulateItemResult::NeedsJumping) } fn fminmax_op( diff --git a/src/tools/miri/src/shims/mod.rs b/src/tools/miri/src/shims/mod.rs index 85c9a202f7d..975efe29b4b 100644 --- a/src/tools/miri/src/shims/mod.rs +++ b/src/tools/miri/src/shims/mod.rs @@ -16,3 +16,13 @@ pub mod os_str; pub mod panic; pub mod time; pub mod tls; + +/// What needs to be done after emulating an item (a shim or an intrinsic) is done. +pub enum EmulateItemResult { + /// The caller is expected to jump to the return block. + NeedsJumping, + /// Jumping has already been taken care of. + AlreadyJumped, + /// The item is not supported. + NotSupported, +} diff --git a/src/tools/miri/src/shims/panic.rs b/src/tools/miri/src/shims/panic.rs index bb31ef733cf..4444d297469 100644 --- a/src/tools/miri/src/shims/panic.rs +++ b/src/tools/miri/src/shims/panic.rs @@ -30,7 +30,7 @@ pub struct CatchUnwindData<'tcx> { /// The return place from the original call to `try`. dest: MPlaceTy<'tcx, Provenance>, /// The return block from the original call to `try`. - ret: mir::BasicBlock, + ret: Option, } impl VisitProvenance for CatchUnwindData<'_> { @@ -73,7 +73,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { &mut self, args: &[OpTy<'tcx, Provenance>], dest: &MPlaceTy<'tcx, Provenance>, - ret: mir::BasicBlock, + ret: Option, ) -> InterpResult<'tcx> { let this = self.eval_context_mut(); @@ -103,7 +103,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { &[data.into()], None, // Directly return to caller. - StackPopCleanup::Goto { ret: Some(ret), unwind: mir::UnwindAction::Continue }, + StackPopCleanup::Goto { ret, unwind: mir::UnwindAction::Continue }, )?; // We ourselves will return `0`, eventually (will be overwritten if we catch a panic). @@ -155,7 +155,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { None, // Directly return to caller of `try`. StackPopCleanup::Goto { - ret: Some(catch_unwind.ret), + ret: catch_unwind.ret, unwind: mir::UnwindAction::Continue, }, )?; diff --git a/src/tools/miri/src/shims/unix/foreign_items.rs b/src/tools/miri/src/shims/unix/foreign_items.rs index bd299aaa125..7f6a3ba0887 100644 --- a/src/tools/miri/src/shims/unix/foreign_items.rs +++ b/src/tools/miri/src/shims/unix/foreign_items.rs @@ -9,7 +9,6 @@ use rustc_target::spec::abi::Abi; use crate::shims::alloc::EvalContextExt as _; use crate::shims::unix::*; use crate::*; -use shims::foreign_items::EmulateForeignItemResult; use shims::unix::freebsd::foreign_items as freebsd; use shims::unix::linux::foreign_items as linux; @@ -43,7 +42,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { abi: Abi, args: &[OpTy<'tcx, Provenance>], dest: &MPlaceTy<'tcx, Provenance>, - ) -> InterpResult<'tcx, EmulateForeignItemResult> { + ) -> InterpResult<'tcx, EmulateItemResult> { let this = self.eval_context_mut(); // See `fn emulate_foreign_item_inner` in `shims/foreign_items.rs` for the general pattern. @@ -750,11 +749,11 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { "freebsd" => freebsd::EvalContextExt::emulate_foreign_item_inner(this, link_name, abi, args, dest), "linux" => linux::EvalContextExt::emulate_foreign_item_inner(this, link_name, abi, args, dest), "macos" => macos::EvalContextExt::emulate_foreign_item_inner(this, link_name, abi, args, dest), - _ => Ok(EmulateForeignItemResult::NotSupported), + _ => Ok(EmulateItemResult::NotSupported), }; } }; - Ok(EmulateForeignItemResult::NeedsJumping) + Ok(EmulateItemResult::NeedsJumping) } } diff --git a/src/tools/miri/src/shims/unix/freebsd/foreign_items.rs b/src/tools/miri/src/shims/unix/freebsd/foreign_items.rs index ffb583123d4..1e0e7d16320 100644 --- a/src/tools/miri/src/shims/unix/freebsd/foreign_items.rs +++ b/src/tools/miri/src/shims/unix/freebsd/foreign_items.rs @@ -3,7 +3,6 @@ use rustc_target::spec::abi::Abi; use crate::shims::unix::*; use crate::*; -use shims::foreign_items::EmulateForeignItemResult; pub fn is_dyn_sym(_name: &str) -> bool { false @@ -17,7 +16,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { abi: Abi, args: &[OpTy<'tcx, Provenance>], dest: &MPlaceTy<'tcx, Provenance>, - ) -> InterpResult<'tcx, EmulateForeignItemResult> { + ) -> InterpResult<'tcx, EmulateItemResult> { let this = self.eval_context_mut(); match link_name.as_str() { // Threading @@ -97,8 +96,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { this.write_scalar(errno_place.to_ref(this).to_scalar(), dest)?; } - _ => return Ok(EmulateForeignItemResult::NotSupported), + _ => return Ok(EmulateItemResult::NotSupported), } - Ok(EmulateForeignItemResult::NeedsJumping) + Ok(EmulateItemResult::NeedsJumping) } } diff --git a/src/tools/miri/src/shims/unix/linux/foreign_items.rs b/src/tools/miri/src/shims/unix/linux/foreign_items.rs index 497e8bee70e..dd4ec8cfaa7 100644 --- a/src/tools/miri/src/shims/unix/linux/foreign_items.rs +++ b/src/tools/miri/src/shims/unix/linux/foreign_items.rs @@ -5,7 +5,6 @@ use crate::machine::SIGRTMAX; use crate::machine::SIGRTMIN; use crate::shims::unix::*; use crate::*; -use shims::foreign_items::EmulateForeignItemResult; use shims::unix::linux::epoll::EvalContextExt as _; use shims::unix::linux::eventfd::EvalContextExt as _; use shims::unix::linux::mem::EvalContextExt as _; @@ -23,7 +22,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { abi: Abi, args: &[OpTy<'tcx, Provenance>], dest: &MPlaceTy<'tcx, Provenance>, - ) -> InterpResult<'tcx, EmulateForeignItemResult> { + ) -> InterpResult<'tcx, EmulateItemResult> { let this = self.eval_context_mut(); // See `fn emulate_foreign_item_inner` in `shims/foreign_items.rs` for the general pattern. @@ -156,7 +155,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { } id => { this.handle_unsupported(format!("can't execute syscall with ID {id}"))?; - return Ok(EmulateForeignItemResult::AlreadyJumped); + return Ok(EmulateItemResult::AlreadyJumped); } } } @@ -204,10 +203,10 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { this.write_null(dest)?; } - _ => return Ok(EmulateForeignItemResult::NotSupported), + _ => return Ok(EmulateItemResult::NotSupported), }; - Ok(EmulateForeignItemResult::NeedsJumping) + Ok(EmulateItemResult::NeedsJumping) } } diff --git a/src/tools/miri/src/shims/unix/macos/foreign_items.rs b/src/tools/miri/src/shims/unix/macos/foreign_items.rs index 66a8dce753f..912623b7225 100644 --- a/src/tools/miri/src/shims/unix/macos/foreign_items.rs +++ b/src/tools/miri/src/shims/unix/macos/foreign_items.rs @@ -3,7 +3,6 @@ use rustc_target::spec::abi::Abi; use crate::shims::unix::*; use crate::*; -use shims::foreign_items::EmulateForeignItemResult; pub fn is_dyn_sym(_name: &str) -> bool { false @@ -17,7 +16,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { abi: Abi, args: &[OpTy<'tcx, Provenance>], dest: &MPlaceTy<'tcx, Provenance>, - ) -> InterpResult<'tcx, EmulateForeignItemResult> { + ) -> InterpResult<'tcx, EmulateItemResult> { let this = self.eval_context_mut(); // See `fn emulate_foreign_item_inner` in `shims/foreign_items.rs` for the general pattern. @@ -175,9 +174,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { this.write_scalar(res, dest)?; } - _ => return Ok(EmulateForeignItemResult::NotSupported), + _ => return Ok(EmulateItemResult::NotSupported), }; - Ok(EmulateForeignItemResult::NeedsJumping) + Ok(EmulateItemResult::NeedsJumping) } } diff --git a/src/tools/miri/src/shims/windows/foreign_items.rs b/src/tools/miri/src/shims/windows/foreign_items.rs index e8ae80261c6..08aee04254b 100644 --- a/src/tools/miri/src/shims/windows/foreign_items.rs +++ b/src/tools/miri/src/shims/windows/foreign_items.rs @@ -12,7 +12,6 @@ use crate::shims::alloc::EvalContextExt as _; use crate::shims::os_str::bytes_to_os_str; use crate::shims::windows::*; use crate::*; -use shims::foreign_items::EmulateForeignItemResult; use shims::windows::handle::{Handle, PseudoHandle}; fn is_dyn_sym(name: &str) -> bool { @@ -86,7 +85,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { abi: Abi, args: &[OpTy<'tcx, Provenance>], dest: &MPlaceTy<'tcx, Provenance>, - ) -> InterpResult<'tcx, EmulateForeignItemResult> { + ) -> InterpResult<'tcx, EmulateItemResult> { let this = self.eval_context_mut(); // See `fn emulate_foreign_item_inner` in `shims/foreign_items.rs` for the general pattern. @@ -721,9 +720,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { this.write_null(dest)?; } - _ => return Ok(EmulateForeignItemResult::NotSupported), + _ => return Ok(EmulateItemResult::NotSupported), } - Ok(EmulateForeignItemResult::NeedsJumping) + Ok(EmulateItemResult::NeedsJumping) } } diff --git a/src/tools/miri/src/shims/x86/aesni.rs b/src/tools/miri/src/shims/x86/aesni.rs index 6c090d877ea..8dc3748a12d 100644 --- a/src/tools/miri/src/shims/x86/aesni.rs +++ b/src/tools/miri/src/shims/x86/aesni.rs @@ -4,7 +4,6 @@ use rustc_span::Symbol; use rustc_target::spec::abi::Abi; use crate::*; -use shims::foreign_items::EmulateForeignItemResult; impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {} pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: @@ -16,7 +15,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: abi: Abi, args: &[OpTy<'tcx, Provenance>], dest: &MPlaceTy<'tcx, Provenance>, - ) -> InterpResult<'tcx, EmulateForeignItemResult> { + ) -> InterpResult<'tcx, EmulateItemResult> { let this = self.eval_context_mut(); this.expect_target_feature_for_intrinsic(link_name, "aes")?; // Prefix should have already been checked. @@ -126,9 +125,9 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: } // TODO: Implement the `llvm.x86.aesni.aeskeygenassist` when possible // with an external crate. - _ => return Ok(EmulateForeignItemResult::NotSupported), + _ => return Ok(EmulateItemResult::NotSupported), } - Ok(EmulateForeignItemResult::NeedsJumping) + Ok(EmulateItemResult::NeedsJumping) } } diff --git a/src/tools/miri/src/shims/x86/avx.rs b/src/tools/miri/src/shims/x86/avx.rs index 41c20d768f7..86ef180a448 100644 --- a/src/tools/miri/src/shims/x86/avx.rs +++ b/src/tools/miri/src/shims/x86/avx.rs @@ -11,7 +11,6 @@ use super::{ FloatBinOp, FloatUnaryOp, }; use crate::*; -use shims::foreign_items::EmulateForeignItemResult; impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {} pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: @@ -23,7 +22,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: abi: Abi, args: &[OpTy<'tcx, Provenance>], dest: &MPlaceTy<'tcx, Provenance>, - ) -> InterpResult<'tcx, EmulateForeignItemResult> { + ) -> InterpResult<'tcx, EmulateItemResult> { let this = self.eval_context_mut(); this.expect_target_feature_for_intrinsic(link_name, "avx")?; // Prefix should have already been checked. @@ -343,8 +342,8 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: this.write_scalar(Scalar::from_i32(res.into()), dest)?; } - _ => return Ok(EmulateForeignItemResult::NotSupported), + _ => return Ok(EmulateItemResult::NotSupported), } - Ok(EmulateForeignItemResult::NeedsJumping) + Ok(EmulateItemResult::NeedsJumping) } } diff --git a/src/tools/miri/src/shims/x86/avx2.rs b/src/tools/miri/src/shims/x86/avx2.rs index bbf53f9f1e5..6e3468c0189 100644 --- a/src/tools/miri/src/shims/x86/avx2.rs +++ b/src/tools/miri/src/shims/x86/avx2.rs @@ -9,7 +9,6 @@ use super::{ packuswb, pmulhrsw, psign, shift_simd_by_scalar, shift_simd_by_simd, ShiftOp, }; use crate::*; -use shims::foreign_items::EmulateForeignItemResult; impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {} pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: @@ -21,7 +20,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: abi: Abi, args: &[OpTy<'tcx, Provenance>], dest: &MPlaceTy<'tcx, Provenance>, - ) -> InterpResult<'tcx, EmulateForeignItemResult> { + ) -> InterpResult<'tcx, EmulateItemResult> { let this = self.eval_context_mut(); this.expect_target_feature_for_intrinsic(link_name, "avx2")?; // Prefix should have already been checked. @@ -437,8 +436,8 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: shift_simd_by_simd(this, left, right, which, dest)?; } - _ => return Ok(EmulateForeignItemResult::NotSupported), + _ => return Ok(EmulateItemResult::NotSupported), } - Ok(EmulateForeignItemResult::NeedsJumping) + Ok(EmulateItemResult::NeedsJumping) } } diff --git a/src/tools/miri/src/shims/x86/mod.rs b/src/tools/miri/src/shims/x86/mod.rs index cf4d6a04bec..2ab2ae85905 100644 --- a/src/tools/miri/src/shims/x86/mod.rs +++ b/src/tools/miri/src/shims/x86/mod.rs @@ -10,7 +10,6 @@ use rustc_target::spec::abi::Abi; use crate::*; use helpers::bool_to_simd_element; -use shims::foreign_items::EmulateForeignItemResult; mod aesni; mod avx; @@ -31,7 +30,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: abi: Abi, args: &[OpTy<'tcx, Provenance>], dest: &MPlaceTy<'tcx, Provenance>, - ) -> InterpResult<'tcx, EmulateForeignItemResult> { + ) -> InterpResult<'tcx, EmulateItemResult> { let this = self.eval_context_mut(); // Prefix should have already been checked. let unprefixed_name = link_name.as_str().strip_prefix("llvm.x86.").unwrap(); @@ -43,7 +42,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: // https://www.intel.com/content/www/us/en/docs/cpp-compiler/developer-guide-reference/2021-8/addcarry-u32-addcarry-u64.html "addcarry.32" | "addcarry.64" => { if unprefixed_name == "addcarry.64" && this.tcx.sess.target.arch != "x86_64" { - return Ok(EmulateForeignItemResult::NotSupported); + return Ok(EmulateItemResult::NotSupported); } let [c_in, a, b] = this.check_shim(abi, Abi::Unadjusted, link_name, args)?; @@ -69,7 +68,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: // https://www.intel.com/content/www/us/en/docs/cpp-compiler/developer-guide-reference/2021-8/subborrow-u32-subborrow-u64.html "subborrow.32" | "subborrow.64" => { if unprefixed_name == "subborrow.64" && this.tcx.sess.target.arch != "x86_64" { - return Ok(EmulateForeignItemResult::NotSupported); + return Ok(EmulateItemResult::NotSupported); } let [b_in, a, b] = this.check_shim(abi, Abi::Unadjusted, link_name, args)?; @@ -143,9 +142,9 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: ); } - _ => return Ok(EmulateForeignItemResult::NotSupported), + _ => return Ok(EmulateItemResult::NotSupported), } - Ok(EmulateForeignItemResult::NeedsJumping) + Ok(EmulateItemResult::NeedsJumping) } } diff --git a/src/tools/miri/src/shims/x86/sse.rs b/src/tools/miri/src/shims/x86/sse.rs index 17608837319..ea967a8cf72 100644 --- a/src/tools/miri/src/shims/x86/sse.rs +++ b/src/tools/miri/src/shims/x86/sse.rs @@ -8,7 +8,6 @@ use super::{ FloatUnaryOp, }; use crate::*; -use shims::foreign_items::EmulateForeignItemResult; impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {} pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: @@ -20,7 +19,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: abi: Abi, args: &[OpTy<'tcx, Provenance>], dest: &MPlaceTy<'tcx, Provenance>, - ) -> InterpResult<'tcx, EmulateForeignItemResult> { + ) -> InterpResult<'tcx, EmulateItemResult> { let this = self.eval_context_mut(); this.expect_target_feature_for_intrinsic(link_name, "sse")?; // Prefix should have already been checked. @@ -211,8 +210,8 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: this.copy_op(&this.project_index(&left, i)?, &this.project_index(&dest, i)?)?; } } - _ => return Ok(EmulateForeignItemResult::NotSupported), + _ => return Ok(EmulateItemResult::NotSupported), } - Ok(EmulateForeignItemResult::NeedsJumping) + Ok(EmulateItemResult::NeedsJumping) } } diff --git a/src/tools/miri/src/shims/x86/sse2.rs b/src/tools/miri/src/shims/x86/sse2.rs index c9ed751d36c..31fa66a496f 100644 --- a/src/tools/miri/src/shims/x86/sse2.rs +++ b/src/tools/miri/src/shims/x86/sse2.rs @@ -7,7 +7,6 @@ use super::{ packuswb, shift_simd_by_scalar, FloatBinOp, ShiftOp, }; use crate::*; -use shims::foreign_items::EmulateForeignItemResult; impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {} pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: @@ -19,7 +18,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: abi: Abi, args: &[OpTy<'tcx, Provenance>], dest: &MPlaceTy<'tcx, Provenance>, - ) -> InterpResult<'tcx, EmulateForeignItemResult> { + ) -> InterpResult<'tcx, EmulateItemResult> { let this = self.eval_context_mut(); this.expect_target_feature_for_intrinsic(link_name, "sse2")?; // Prefix should have already been checked. @@ -387,8 +386,8 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: this.copy_op(&this.project_index(&left, i)?, &this.project_index(&dest, i)?)?; } } - _ => return Ok(EmulateForeignItemResult::NotSupported), + _ => return Ok(EmulateItemResult::NotSupported), } - Ok(EmulateForeignItemResult::NeedsJumping) + Ok(EmulateItemResult::NeedsJumping) } } diff --git a/src/tools/miri/src/shims/x86/sse3.rs b/src/tools/miri/src/shims/x86/sse3.rs index 5ac30dca79a..8de339eb9e5 100644 --- a/src/tools/miri/src/shims/x86/sse3.rs +++ b/src/tools/miri/src/shims/x86/sse3.rs @@ -4,7 +4,6 @@ use rustc_target::spec::abi::Abi; use super::horizontal_bin_op; use crate::*; -use shims::foreign_items::EmulateForeignItemResult; impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {} pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: @@ -16,7 +15,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: abi: Abi, args: &[OpTy<'tcx, Provenance>], dest: &MPlaceTy<'tcx, Provenance>, - ) -> InterpResult<'tcx, EmulateForeignItemResult> { + ) -> InterpResult<'tcx, EmulateItemResult> { let this = self.eval_context_mut(); this.expect_target_feature_for_intrinsic(link_name, "sse3")?; // Prefix should have already been checked. @@ -50,8 +49,8 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: this.mem_copy(src_ptr, dest.ptr(), dest.layout.size, /*nonoverlapping*/ true)?; } - _ => return Ok(EmulateForeignItemResult::NotSupported), + _ => return Ok(EmulateItemResult::NotSupported), } - Ok(EmulateForeignItemResult::NeedsJumping) + Ok(EmulateItemResult::NeedsJumping) } } diff --git a/src/tools/miri/src/shims/x86/sse41.rs b/src/tools/miri/src/shims/x86/sse41.rs index 19bc27421d3..011a7a16c68 100644 --- a/src/tools/miri/src/shims/x86/sse41.rs +++ b/src/tools/miri/src/shims/x86/sse41.rs @@ -3,7 +3,6 @@ use rustc_target::spec::abi::Abi; use super::{conditional_dot_product, mpsadbw, packusdw, round_all, round_first, test_bits_masked}; use crate::*; -use shims::foreign_items::EmulateForeignItemResult; impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {} pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: @@ -15,7 +14,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: abi: Abi, args: &[OpTy<'tcx, Provenance>], dest: &MPlaceTy<'tcx, Provenance>, - ) -> InterpResult<'tcx, EmulateForeignItemResult> { + ) -> InterpResult<'tcx, EmulateItemResult> { let this = self.eval_context_mut(); this.expect_target_feature_for_intrinsic(link_name, "sse4.1")?; // Prefix should have already been checked. @@ -175,8 +174,8 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: this.write_scalar(Scalar::from_i32(res.into()), dest)?; } - _ => return Ok(EmulateForeignItemResult::NotSupported), + _ => return Ok(EmulateItemResult::NotSupported), } - Ok(EmulateForeignItemResult::NeedsJumping) + Ok(EmulateItemResult::NeedsJumping) } } diff --git a/src/tools/miri/src/shims/x86/ssse3.rs b/src/tools/miri/src/shims/x86/ssse3.rs index 4f8e52dbb7d..d30de430088 100644 --- a/src/tools/miri/src/shims/x86/ssse3.rs +++ b/src/tools/miri/src/shims/x86/ssse3.rs @@ -4,7 +4,6 @@ use rustc_target::spec::abi::Abi; use super::{horizontal_bin_op, int_abs, pmulhrsw, psign}; use crate::*; -use shims::foreign_items::EmulateForeignItemResult; impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {} pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: @@ -16,7 +15,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: abi: Abi, args: &[OpTy<'tcx, Provenance>], dest: &MPlaceTy<'tcx, Provenance>, - ) -> InterpResult<'tcx, EmulateForeignItemResult> { + ) -> InterpResult<'tcx, EmulateItemResult> { let this = self.eval_context_mut(); this.expect_target_feature_for_intrinsic(link_name, "ssse3")?; // Prefix should have already been checked. @@ -136,8 +135,8 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: psign(this, left, right, dest)?; } - _ => return Ok(EmulateForeignItemResult::NotSupported), + _ => return Ok(EmulateItemResult::NotSupported), } - Ok(EmulateForeignItemResult::NeedsJumping) + Ok(EmulateItemResult::NeedsJumping) } }