mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-26 08:44:35 +00:00
Merge from rustc
This commit is contained in:
commit
8db37a3cb5
@ -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(
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
}
|
||||
|
||||
|
@ -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]`
|
||||
|
||||
|
@ -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()
|
||||
{
|
||||
|
@ -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 {
|
||||
|
@ -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> [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> [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
|
||||
|
@ -364,6 +364,27 @@ where
|
||||
self.pos += n as u64;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
|
||||
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<usize> {
|
||||
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")]
|
||||
|
@ -329,8 +329,9 @@ impl Read for &[u8] {
|
||||
#[inline]
|
||||
fn read_to_string(&mut self, buf: &mut String) -> io::Result<usize> {
|
||||
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)
|
||||
}
|
||||
@ -473,14 +474,8 @@ impl<A: Allocator> Read for VecDeque<u8, A> {
|
||||
|
||||
#[inline]
|
||||
fn read_to_string(&mut self, buf: &mut String) -> io::Result<usize> {
|
||||
// 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.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)) }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
|
@ -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<u8>) -> io::Result<usize> {
|
||||
self.inner.read_to_end(buf)
|
||||
}
|
||||
}
|
||||
|
||||
impl AsInner<AnonPipe> for ChildStderr {
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -37,58 +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).
|
||||
@ -99,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<mir::BasicBlock>,
|
||||
) -> InterpResult<'tcx, EmulateItemResult> {
|
||||
let this = self.eval_context_mut();
|
||||
|
||||
if let Some(name) = intrinsic_name.strip_prefix("atomic_") {
|
||||
@ -110,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)?;
|
||||
@ -433,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)
|
||||
}
|
||||
}
|
||||
|
@ -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(
|
||||
|
@ -103,6 +103,7 @@ pub use crate::shims::os_str::EvalContextExt as _;
|
||||
pub use crate::shims::panic::{CatchUnwindData, EvalContextExt as _};
|
||||
pub use crate::shims::time::EvalContextExt as _;
|
||||
pub use crate::shims::tls::TlsData;
|
||||
pub use crate::shims::EmulateItemResult;
|
||||
|
||||
pub use crate::alloc_addresses::{EvalContextExt as _, ProvenanceMode};
|
||||
pub use crate::borrow_tracker::stacked_borrows::{
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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_foreign_item(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));
|
||||
}
|
||||
@ -252,7 +205,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.
|
||||
@ -263,7 +217,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);
|
||||
}
|
||||
}
|
||||
|
||||
@ -307,6 +261,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();
|
||||
@ -371,29 +330,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" => {
|
||||
@ -407,7 +361,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;
|
||||
@ -451,6 +404,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)?;
|
||||
@ -513,7 +485,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!(),
|
||||
}
|
||||
@ -573,7 +545,7 @@ trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
||||
}
|
||||
"miri_dealloc" => {
|
||||
default(this)?;
|
||||
return Ok(EmulateForeignItemResult::NeedsJumping);
|
||||
return Ok(EmulateItemResult::NeedsJumping);
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
@ -975,11 +947,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)
|
||||
}
|
||||
}
|
||||
|
@ -15,3 +15,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,
|
||||
}
|
||||
|
@ -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<mir::BasicBlock>,
|
||||
}
|
||||
|
||||
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<mir::BasicBlock>,
|
||||
) -> 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,
|
||||
},
|
||||
)?;
|
||||
|
@ -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.
|
||||
@ -731,11 +730,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)
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
@ -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.
|
||||
@ -147,7 +146,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
||||
this.handle_unsupported_foreign_item(format!(
|
||||
"can't execute syscall with ID {id}"
|
||||
))?;
|
||||
return Ok(EmulateForeignItemResult::AlreadyJumped);
|
||||
return Ok(EmulateItemResult::AlreadyJumped);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -208,10 +207,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)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
@ -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};
|
||||
|
||||
pub 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)
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
@ -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.
|
||||
@ -439,8 +438,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)
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user