Auto merge of #134550 - jhpratt:rollup-wsfmo59, r=jhpratt

Rollup of 6 pull requests

Successful merges:

 - #126118 (docs: Mention `spare_capacity_mut()` in `Vec::set_len`)
 - #132830 (Rename `elem_offset` to `element_offset`)
 - #133103 (Pass FnAbi to find_mir_or_eval_fn)
 - #134321 (Hide `= _` as associated constant value inside impl blocks)
 - #134518 (fix typos in the example code in the doc comments of `Ipv4Addr::from_bits()`, `Ipv6Addr::from_bits()` & `Ipv6Addr::to_bits()`)
 - #134521 (Arbitrary self types v2: roll loop.)

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2024-12-20 07:27:15 +00:00
commit 8a1f8039a7
51 changed files with 712 additions and 583 deletions

View file

@ -1,9 +1,11 @@
use rustc_middle::mir::interpret::{AllocId, ConstAllocation, InterpResult}; use rustc_middle::mir::interpret::{AllocId, ConstAllocation, InterpResult};
use rustc_middle::mir::*; use rustc_middle::mir::*;
use rustc_middle::query::TyCtxtAt; use rustc_middle::query::TyCtxtAt;
use rustc_middle::ty::Ty;
use rustc_middle::ty::layout::TyAndLayout; use rustc_middle::ty::layout::TyAndLayout;
use rustc_middle::{bug, span_bug, ty}; use rustc_middle::{bug, span_bug, ty};
use rustc_span::def_id::DefId; use rustc_span::def_id::DefId;
use rustc_target::callconv::FnAbi;
use crate::interpret::{ use crate::interpret::{
self, HasStaticRootDefId, ImmTy, Immediate, InterpCx, PointerArithmetic, interp_ok, self, HasStaticRootDefId, ImmTy, Immediate, InterpCx, PointerArithmetic, interp_ok,
@ -86,7 +88,7 @@ impl<'tcx> interpret::Machine<'tcx> for DummyMachine {
fn find_mir_or_eval_fn( fn find_mir_or_eval_fn(
_ecx: &mut InterpCx<'tcx, Self>, _ecx: &mut InterpCx<'tcx, Self>,
_instance: ty::Instance<'tcx>, _instance: ty::Instance<'tcx>,
_abi: rustc_abi::ExternAbi, _abi: &FnAbi<'tcx, Ty<'tcx>>,
_args: &[interpret::FnArg<'tcx, Self::Provenance>], _args: &[interpret::FnArg<'tcx, Self::Provenance>],
_destination: &interpret::MPlaceTy<'tcx, Self::Provenance>, _destination: &interpret::MPlaceTy<'tcx, Self::Provenance>,
_target: Option<BasicBlock>, _target: Option<BasicBlock>,

View file

@ -2,7 +2,7 @@ use std::borrow::{Borrow, Cow};
use std::fmt; use std::fmt;
use std::hash::Hash; use std::hash::Hash;
use rustc_abi::{Align, ExternAbi, Size}; use rustc_abi::{Align, Size};
use rustc_ast::Mutability; use rustc_ast::Mutability;
use rustc_data_structures::fx::{FxHashMap, FxIndexMap, IndexEntry}; use rustc_data_structures::fx::{FxHashMap, FxIndexMap, IndexEntry};
use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::def_id::{DefId, LocalDefId};
@ -14,6 +14,7 @@ use rustc_middle::ty::layout::{HasTypingEnv, TyAndLayout};
use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_middle::{bug, mir}; use rustc_middle::{bug, mir};
use rustc_span::{Span, Symbol, sym}; use rustc_span::{Span, Symbol, sym};
use rustc_target::callconv::FnAbi;
use tracing::debug; use tracing::debug;
use super::error::*; use super::error::*;
@ -339,7 +340,7 @@ impl<'tcx> interpret::Machine<'tcx> for CompileTimeMachine<'tcx> {
fn find_mir_or_eval_fn( fn find_mir_or_eval_fn(
ecx: &mut InterpCx<'tcx, Self>, ecx: &mut InterpCx<'tcx, Self>,
orig_instance: ty::Instance<'tcx>, orig_instance: ty::Instance<'tcx>,
_abi: ExternAbi, _abi: &FnAbi<'tcx, Ty<'tcx>>,
args: &[FnArg<'tcx>], args: &[FnArg<'tcx>],
dest: &MPlaceTy<'tcx>, dest: &MPlaceTy<'tcx>,
ret: Option<mir::BasicBlock>, ret: Option<mir::BasicBlock>,

View file

@ -519,7 +519,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
return M::call_extra_fn( return M::call_extra_fn(
self, self,
extra, extra,
caller_abi, caller_fn_abi,
args, args,
destination, destination,
target, target,
@ -570,7 +570,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
let Some((body, instance)) = M::find_mir_or_eval_fn( let Some((body, instance)) = M::find_mir_or_eval_fn(
self, self,
instance, instance,
caller_abi, caller_fn_abi,
args, args,
destination, destination,
target, target,

View file

@ -6,7 +6,7 @@ use std::borrow::{Borrow, Cow};
use std::fmt::Debug; use std::fmt::Debug;
use std::hash::Hash; use std::hash::Hash;
use rustc_abi::{Align, ExternAbi, Size}; use rustc_abi::{Align, Size};
use rustc_apfloat::{Float, FloatConvert}; use rustc_apfloat::{Float, FloatConvert};
use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece}; use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece};
use rustc_middle::query::TyCtxtAt; use rustc_middle::query::TyCtxtAt;
@ -15,6 +15,7 @@ use rustc_middle::ty::layout::TyAndLayout;
use rustc_middle::{mir, ty}; use rustc_middle::{mir, ty};
use rustc_span::Span; use rustc_span::Span;
use rustc_span::def_id::DefId; use rustc_span::def_id::DefId;
use rustc_target::callconv::FnAbi;
use super::{ use super::{
AllocBytes, AllocId, AllocKind, AllocRange, Allocation, CTFE_ALLOC_SALT, ConstAllocation, AllocBytes, AllocId, AllocKind, AllocRange, Allocation, CTFE_ALLOC_SALT, ConstAllocation,
@ -201,7 +202,7 @@ pub trait Machine<'tcx>: Sized {
fn find_mir_or_eval_fn( fn find_mir_or_eval_fn(
ecx: &mut InterpCx<'tcx, Self>, ecx: &mut InterpCx<'tcx, Self>,
instance: ty::Instance<'tcx>, instance: ty::Instance<'tcx>,
abi: ExternAbi, abi: &FnAbi<'tcx, Ty<'tcx>>,
args: &[FnArg<'tcx, Self::Provenance>], args: &[FnArg<'tcx, Self::Provenance>],
destination: &MPlaceTy<'tcx, Self::Provenance>, destination: &MPlaceTy<'tcx, Self::Provenance>,
target: Option<mir::BasicBlock>, target: Option<mir::BasicBlock>,
@ -213,7 +214,7 @@ pub trait Machine<'tcx>: Sized {
fn call_extra_fn( fn call_extra_fn(
ecx: &mut InterpCx<'tcx, Self>, ecx: &mut InterpCx<'tcx, Self>,
fn_val: Self::ExtraFnVal, fn_val: Self::ExtraFnVal,
abi: ExternAbi, abi: &FnAbi<'tcx, Ty<'tcx>>,
args: &[FnArg<'tcx, Self::Provenance>], args: &[FnArg<'tcx, Self::Provenance>],
destination: &MPlaceTy<'tcx, Self::Provenance>, destination: &MPlaceTy<'tcx, Self::Provenance>,
target: Option<mir::BasicBlock>, target: Option<mir::BasicBlock>,
@ -656,7 +657,7 @@ pub macro compile_time_machine(<$tcx: lifetime>) {
fn call_extra_fn( fn call_extra_fn(
_ecx: &mut InterpCx<$tcx, Self>, _ecx: &mut InterpCx<$tcx, Self>,
fn_val: !, fn_val: !,
_abi: ExternAbi, _abi: &FnAbi<$tcx, Ty<$tcx>>,
_args: &[FnArg<$tcx>], _args: &[FnArg<$tcx>],
_destination: &MPlaceTy<$tcx, Self::Provenance>, _destination: &MPlaceTy<$tcx, Self::Provenance>,
_target: Option<mir::BasicBlock>, _target: Option<mir::BasicBlock>,

View file

@ -1229,23 +1229,16 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
if let Some(by_value_pick) = by_value_pick { if let Some(by_value_pick) = by_value_pick {
if let Ok(by_value_pick) = by_value_pick.as_ref() { if let Ok(by_value_pick) = by_value_pick.as_ref() {
if by_value_pick.kind == PickKind::InherentImplPick { if by_value_pick.kind == PickKind::InherentImplPick {
if let Err(e) = self.check_for_shadowed_autorefd_method( for mutbl in [hir::Mutability::Not, hir::Mutability::Mut] {
by_value_pick, if let Err(e) = self.check_for_shadowed_autorefd_method(
step, by_value_pick,
self_ty, step,
hir::Mutability::Not, self_ty,
track_unstable_candidates, mutbl,
) { track_unstable_candidates,
return Some(Err(e)); ) {
} return Some(Err(e));
if let Err(e) = self.check_for_shadowed_autorefd_method( }
by_value_pick,
step,
self_ty,
hir::Mutability::Mut,
track_unstable_candidates,
) {
return Some(Err(e));
} }
} }
} }

View file

@ -1824,7 +1824,10 @@ impl<T, A: Allocator> Vec<T, A> {
/// ///
/// # Examples /// # Examples
/// ///
/// This method can be useful for situations in which the vector /// See [`spare_capacity_mut()`] for an example with safe
/// initialization of capacity elements and use of this method.
///
/// `set_len()` can be useful for situations in which the vector
/// is serving as a buffer for other code, particularly over FFI: /// is serving as a buffer for other code, particularly over FFI:
/// ///
/// ```no_run /// ```no_run
@ -1884,6 +1887,8 @@ impl<T, A: Allocator> Vec<T, A> {
/// ///
/// Normally, here, one would use [`clear`] instead to correctly drop /// Normally, here, one would use [`clear`] instead to correctly drop
/// the contents and thus not leak memory. /// the contents and thus not leak memory.
///
/// [`spare_capacity_mut()`]: Vec::spare_capacity_mut
#[inline] #[inline]
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
pub unsafe fn set_len(&mut self, new_len: usize) { pub unsafe fn set_len(&mut self, new_len: usize) {

View file

@ -527,7 +527,7 @@ impl Ipv4Addr {
/// ``` /// ```
/// use std::net::Ipv4Addr; /// use std::net::Ipv4Addr;
/// ///
/// let addr = Ipv4Addr::from(0x12345678); /// let addr = Ipv4Addr::from_bits(0x12345678);
/// assert_eq!(Ipv4Addr::new(0x12, 0x34, 0x56, 0x78), addr); /// assert_eq!(Ipv4Addr::new(0x12, 0x34, 0x56, 0x78), addr);
/// ``` /// ```
#[rustc_const_stable(feature = "ip_bits", since = "1.80.0")] #[rustc_const_stable(feature = "ip_bits", since = "1.80.0")]
@ -1294,7 +1294,7 @@ impl Ipv6Addr {
/// 0x1020, 0x3040, 0x5060, 0x7080, /// 0x1020, 0x3040, 0x5060, 0x7080,
/// 0x90A0, 0xB0C0, 0xD0E0, 0xF00D, /// 0x90A0, 0xB0C0, 0xD0E0, 0xF00D,
/// ); /// );
/// assert_eq!(0x102030405060708090A0B0C0D0E0F00D_u128, u128::from(addr)); /// assert_eq!(0x102030405060708090A0B0C0D0E0F00D_u128, addr.to_bits());
/// ``` /// ```
/// ///
/// ``` /// ```
@ -1330,7 +1330,7 @@ impl Ipv6Addr {
/// ``` /// ```
/// use std::net::Ipv6Addr; /// use std::net::Ipv6Addr;
/// ///
/// let addr = Ipv6Addr::from(0x102030405060708090A0B0C0D0E0F00D_u128); /// let addr = Ipv6Addr::from_bits(0x102030405060708090A0B0C0D0E0F00D_u128);
/// assert_eq!( /// assert_eq!(
/// Ipv6Addr::new( /// Ipv6Addr::new(
/// 0x1020, 0x3040, 0x5060, 0x7080, /// 0x1020, 0x3040, 0x5060, 0x7080,

View file

@ -4641,7 +4641,7 @@ impl<T> [T] {
/// Returns the index that an element reference points to. /// Returns the index that an element reference points to.
/// ///
/// Returns `None` if `element` does not point within the slice or if it points between elements. /// Returns `None` if `element` does not point to the start of an element within the slice.
/// ///
/// This method is useful for extending slice iterators like [`slice::split`]. /// This method is useful for extending slice iterators like [`slice::split`].
/// ///
@ -4661,9 +4661,9 @@ impl<T> [T] {
/// let num = &nums[2]; /// let num = &nums[2];
/// ///
/// assert_eq!(num, &1); /// assert_eq!(num, &1);
/// assert_eq!(nums.elem_offset(num), Some(2)); /// assert_eq!(nums.element_offset(num), Some(2));
/// ``` /// ```
/// Returning `None` with an in-between element: /// Returning `None` with an unaligned element:
/// ``` /// ```
/// #![feature(substr_range)] /// #![feature(substr_range)]
/// ///
@ -4676,12 +4676,12 @@ impl<T> [T] {
/// assert_eq!(ok_elm, &[0, 1]); /// assert_eq!(ok_elm, &[0, 1]);
/// assert_eq!(weird_elm, &[1, 2]); /// assert_eq!(weird_elm, &[1, 2]);
/// ///
/// assert_eq!(arr.elem_offset(ok_elm), Some(0)); // Points to element 0 /// assert_eq!(arr.element_offset(ok_elm), Some(0)); // Points to element 0
/// assert_eq!(arr.elem_offset(weird_elm), None); // Points between element 0 and 1 /// assert_eq!(arr.element_offset(weird_elm), None); // Points between element 0 and 1
/// ``` /// ```
#[must_use] #[must_use]
#[unstable(feature = "substr_range", issue = "126769")] #[unstable(feature = "substr_range", issue = "126769")]
pub fn elem_offset(&self, element: &T) -> Option<usize> { pub fn element_offset(&self, element: &T) -> Option<usize> {
if T::IS_ZST { if T::IS_ZST {
panic!("elements are zero-sized"); panic!("elements are zero-sized");
} }
@ -4702,7 +4702,8 @@ impl<T> [T] {
/// Returns the range of indices that a subslice points to. /// Returns the range of indices that a subslice points to.
/// ///
/// Returns `None` if `subslice` does not point within the slice or if it points between elements. /// Returns `None` if `subslice` does not point within the slice or if it is not aligned with the
/// elements in the slice.
/// ///
/// This method **does not compare elements**. Instead, this method finds the location in the slice that /// This method **does not compare elements**. Instead, this method finds the location in the slice that
/// `subslice` was obtained from. To find the index of a subslice via comparison, instead use /// `subslice` was obtained from. To find the index of a subslice via comparison, instead use

View file

@ -1222,14 +1222,16 @@ fn clean_trait_item<'tcx>(trait_item: &hir::TraitItem<'tcx>, cx: &mut DocContext
let local_did = trait_item.owner_id.to_def_id(); let local_did = trait_item.owner_id.to_def_id();
cx.with_param_env(local_did, |cx| { cx.with_param_env(local_did, |cx| {
let inner = match trait_item.kind { let inner = match trait_item.kind {
hir::TraitItemKind::Const(ty, Some(default)) => AssocConstItem(Box::new(Constant { hir::TraitItemKind::Const(ty, Some(default)) => {
generics: enter_impl_trait(cx, |cx| clean_generics(trait_item.generics, cx)), ProvidedAssocConstItem(Box::new(Constant {
kind: ConstantKind::Local { def_id: local_did, body: default }, generics: enter_impl_trait(cx, |cx| clean_generics(trait_item.generics, cx)),
type_: clean_ty(ty, cx), kind: ConstantKind::Local { def_id: local_did, body: default },
})), type_: clean_ty(ty, cx),
}))
}
hir::TraitItemKind::Const(ty, None) => { hir::TraitItemKind::Const(ty, None) => {
let generics = enter_impl_trait(cx, |cx| clean_generics(trait_item.generics, cx)); let generics = enter_impl_trait(cx, |cx| clean_generics(trait_item.generics, cx));
TyAssocConstItem(generics, Box::new(clean_ty(ty, cx))) RequiredAssocConstItem(generics, Box::new(clean_ty(ty, cx)))
} }
hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Provided(body)) => { hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Provided(body)) => {
let m = clean_function(cx, sig, trait_item.generics, FunctionArgs::Body(body)); let m = clean_function(cx, sig, trait_item.generics, FunctionArgs::Body(body));
@ -1237,7 +1239,7 @@ fn clean_trait_item<'tcx>(trait_item: &hir::TraitItem<'tcx>, cx: &mut DocContext
} }
hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Required(names)) => { hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Required(names)) => {
let m = clean_function(cx, sig, trait_item.generics, FunctionArgs::Names(names)); let m = clean_function(cx, sig, trait_item.generics, FunctionArgs::Names(names));
TyMethodItem(m) RequiredMethodItem(m)
} }
hir::TraitItemKind::Type(bounds, Some(default)) => { hir::TraitItemKind::Type(bounds, Some(default)) => {
let generics = enter_impl_trait(cx, |cx| clean_generics(trait_item.generics, cx)); let generics = enter_impl_trait(cx, |cx| clean_generics(trait_item.generics, cx));
@ -1257,7 +1259,7 @@ fn clean_trait_item<'tcx>(trait_item: &hir::TraitItem<'tcx>, cx: &mut DocContext
hir::TraitItemKind::Type(bounds, None) => { hir::TraitItemKind::Type(bounds, None) => {
let generics = enter_impl_trait(cx, |cx| clean_generics(trait_item.generics, cx)); let generics = enter_impl_trait(cx, |cx| clean_generics(trait_item.generics, cx));
let bounds = bounds.iter().filter_map(|x| clean_generic_bound(x, cx)).collect(); let bounds = bounds.iter().filter_map(|x| clean_generic_bound(x, cx)).collect();
TyAssocTypeItem(generics, bounds) RequiredAssocTypeItem(generics, bounds)
} }
}; };
Item::from_def_id_and_parts(local_did, Some(trait_item.ident.name), inner, cx) Item::from_def_id_and_parts(local_did, Some(trait_item.ident.name), inner, cx)
@ -1271,7 +1273,7 @@ pub(crate) fn clean_impl_item<'tcx>(
let local_did = impl_.owner_id.to_def_id(); let local_did = impl_.owner_id.to_def_id();
cx.with_param_env(local_did, |cx| { cx.with_param_env(local_did, |cx| {
let inner = match impl_.kind { let inner = match impl_.kind {
hir::ImplItemKind::Const(ty, expr) => AssocConstItem(Box::new(Constant { hir::ImplItemKind::Const(ty, expr) => ImplAssocConstItem(Box::new(Constant {
generics: clean_generics(impl_.generics, cx), generics: clean_generics(impl_.generics, cx),
kind: ConstantKind::Local { def_id: local_did, body: expr }, kind: ConstantKind::Local { def_id: local_did, body: expr },
type_: clean_ty(ty, cx), type_: clean_ty(ty, cx),
@ -1320,18 +1322,23 @@ pub(crate) fn clean_middle_assoc_item(assoc_item: &ty::AssocItem, cx: &mut DocCo
); );
simplify::move_bounds_to_generic_parameters(&mut generics); simplify::move_bounds_to_generic_parameters(&mut generics);
let provided = match assoc_item.container { match assoc_item.container {
ty::AssocItemContainer::Impl => true, ty::AssocItemContainer::Impl => ImplAssocConstItem(Box::new(Constant {
ty::AssocItemContainer::Trait => tcx.defaultness(assoc_item.def_id).has_value(),
};
if provided {
AssocConstItem(Box::new(Constant {
generics, generics,
kind: ConstantKind::Extern { def_id: assoc_item.def_id }, kind: ConstantKind::Extern { def_id: assoc_item.def_id },
type_: ty, type_: ty,
})) })),
} else { ty::AssocItemContainer::Trait => {
TyAssocConstItem(generics, Box::new(ty)) if tcx.defaultness(assoc_item.def_id).has_value() {
ProvidedAssocConstItem(Box::new(Constant {
generics,
kind: ConstantKind::Extern { def_id: assoc_item.def_id },
type_: ty,
}))
} else {
RequiredAssocConstItem(generics, Box::new(ty))
}
}
} }
} }
ty::AssocKind::Fn => { ty::AssocKind::Fn => {
@ -1369,7 +1376,7 @@ pub(crate) fn clean_middle_assoc_item(assoc_item: &ty::AssocItem, cx: &mut DocCo
}; };
MethodItem(item, defaultness) MethodItem(item, defaultness)
} else { } else {
TyMethodItem(item) RequiredMethodItem(item)
} }
} }
ty::AssocKind::Type => { ty::AssocKind::Type => {
@ -1486,7 +1493,7 @@ pub(crate) fn clean_middle_assoc_item(assoc_item: &ty::AssocItem, cx: &mut DocCo
bounds, bounds,
) )
} else { } else {
TyAssocTypeItem(generics, bounds) RequiredAssocTypeItem(generics, bounds)
} }
} else { } else {
AssocTypeItem( AssocTypeItem(

View file

@ -545,14 +545,14 @@ impl Item {
pub(crate) fn is_associated_type(&self) -> bool { pub(crate) fn is_associated_type(&self) -> bool {
matches!(self.kind, AssocTypeItem(..) | StrippedItem(box AssocTypeItem(..))) matches!(self.kind, AssocTypeItem(..) | StrippedItem(box AssocTypeItem(..)))
} }
pub(crate) fn is_ty_associated_type(&self) -> bool { pub(crate) fn is_required_associated_type(&self) -> bool {
matches!(self.kind, TyAssocTypeItem(..) | StrippedItem(box TyAssocTypeItem(..))) matches!(self.kind, RequiredAssocTypeItem(..) | StrippedItem(box RequiredAssocTypeItem(..)))
} }
pub(crate) fn is_associated_const(&self) -> bool { pub(crate) fn is_associated_const(&self) -> bool {
matches!(self.kind, AssocConstItem(..) | StrippedItem(box AssocConstItem(..))) matches!(self.kind, ProvidedAssocConstItem(..) | ImplAssocConstItem(..) | StrippedItem(box (ProvidedAssocConstItem(..) | ImplAssocConstItem(..))))
} }
pub(crate) fn is_ty_associated_const(&self) -> bool { pub(crate) fn is_required_associated_const(&self) -> bool {
matches!(self.kind, TyAssocConstItem(..) | StrippedItem(box TyAssocConstItem(..))) matches!(self.kind, RequiredAssocConstItem(..) | StrippedItem(box RequiredAssocConstItem(..)))
} }
pub(crate) fn is_method(&self) -> bool { pub(crate) fn is_method(&self) -> bool {
self.type_() == ItemType::Method self.type_() == ItemType::Method
@ -669,7 +669,9 @@ impl Item {
asyncness: hir::IsAsync::NotAsync, asyncness: hir::IsAsync::NotAsync,
} }
} }
ItemKind::FunctionItem(_) | ItemKind::MethodItem(_, _) | ItemKind::TyMethodItem(_) => { ItemKind::FunctionItem(_)
| ItemKind::MethodItem(_, _)
| ItemKind::RequiredMethodItem(_) => {
let def_id = self.def_id().unwrap(); let def_id = self.def_id().unwrap();
build_fn_header(def_id, tcx, tcx.asyncness(def_id)) build_fn_header(def_id, tcx, tcx.asyncness(def_id))
} }
@ -699,8 +701,13 @@ impl Item {
// Variants always inherit visibility // Variants always inherit visibility
VariantItem(..) | ImplItem(..) => return None, VariantItem(..) | ImplItem(..) => return None,
// Trait items inherit the trait's visibility // Trait items inherit the trait's visibility
AssocConstItem(..) | TyAssocConstItem(..) | AssocTypeItem(..) | TyAssocTypeItem(..) RequiredAssocConstItem(..)
| TyMethodItem(..) | MethodItem(..) => { | ProvidedAssocConstItem(..)
| ImplAssocConstItem(..)
| AssocTypeItem(..)
| RequiredAssocTypeItem(..)
| RequiredMethodItem(..)
| MethodItem(..) => {
let assoc_item = tcx.associated_item(def_id); let assoc_item = tcx.associated_item(def_id);
let is_trait_item = match assoc_item.container { let is_trait_item = match assoc_item.container {
ty::AssocItemContainer::Trait => true, ty::AssocItemContainer::Trait => true,
@ -845,10 +852,10 @@ pub(crate) enum ItemKind {
TraitAliasItem(TraitAlias), TraitAliasItem(TraitAlias),
ImplItem(Box<Impl>), ImplItem(Box<Impl>),
/// A required method in a trait declaration meaning it's only a function signature. /// A required method in a trait declaration meaning it's only a function signature.
TyMethodItem(Box<Function>), RequiredMethodItem(Box<Function>),
/// A method in a trait impl or a provided method in a trait declaration. /// A method in a trait impl or a provided method in a trait declaration.
/// ///
/// Compared to [TyMethodItem], it also contains a method body. /// Compared to [RequiredMethodItem], it also contains a method body.
MethodItem(Box<Function>, Option<hir::Defaultness>), MethodItem(Box<Function>, Option<hir::Defaultness>),
StructFieldItem(Type), StructFieldItem(Type),
VariantItem(Variant), VariantItem(Variant),
@ -862,14 +869,16 @@ pub(crate) enum ItemKind {
ProcMacroItem(ProcMacro), ProcMacroItem(ProcMacro),
PrimitiveItem(PrimitiveType), PrimitiveItem(PrimitiveType),
/// A required associated constant in a trait declaration. /// A required associated constant in a trait declaration.
TyAssocConstItem(Generics, Box<Type>), RequiredAssocConstItem(Generics, Box<Type>),
ConstantItem(Box<Constant>), ConstantItem(Box<Constant>),
/// An associated constant in a trait impl or a provided one in a trait declaration. /// An associated constant in a trait declaration with provided default value.
AssocConstItem(Box<Constant>), ProvidedAssocConstItem(Box<Constant>),
/// An associated constant in an inherent impl or trait impl.
ImplAssocConstItem(Box<Constant>),
/// A required associated type in a trait declaration. /// A required associated type in a trait declaration.
/// ///
/// The bounds may be non-empty if there is a `where` clause. /// The bounds may be non-empty if there is a `where` clause.
TyAssocTypeItem(Generics, Vec<GenericBound>), RequiredAssocTypeItem(Generics, Vec<GenericBound>),
/// An associated type in a trait impl or a provided one in a trait declaration. /// An associated type in a trait impl or a provided one in a trait declaration.
AssocTypeItem(Box<TypeAlias>, Vec<GenericBound>), AssocTypeItem(Box<TypeAlias>, Vec<GenericBound>),
/// An item that has been stripped by a rustdoc pass /// An item that has been stripped by a rustdoc pass
@ -900,7 +909,7 @@ impl ItemKind {
| StaticItem(_) | StaticItem(_)
| ConstantItem(_) | ConstantItem(_)
| TraitAliasItem(_) | TraitAliasItem(_)
| TyMethodItem(_) | RequiredMethodItem(_)
| MethodItem(_, _) | MethodItem(_, _)
| StructFieldItem(_) | StructFieldItem(_)
| ForeignFunctionItem(_, _) | ForeignFunctionItem(_, _)
@ -909,9 +918,10 @@ impl ItemKind {
| MacroItem(_) | MacroItem(_)
| ProcMacroItem(_) | ProcMacroItem(_)
| PrimitiveItem(_) | PrimitiveItem(_)
| TyAssocConstItem(..) | RequiredAssocConstItem(..)
| AssocConstItem(..) | ProvidedAssocConstItem(..)
| TyAssocTypeItem(..) | ImplAssocConstItem(..)
| RequiredAssocTypeItem(..)
| AssocTypeItem(..) | AssocTypeItem(..)
| StrippedItem(_) | StrippedItem(_)
| KeywordItem => [].iter(), | KeywordItem => [].iter(),

View file

@ -82,7 +82,7 @@ pub(crate) trait DocFolder: Sized {
| StaticItem(_) | StaticItem(_)
| ConstantItem(..) | ConstantItem(..)
| TraitAliasItem(_) | TraitAliasItem(_)
| TyMethodItem(_) | RequiredMethodItem(_)
| MethodItem(_, _) | MethodItem(_, _)
| StructFieldItem(_) | StructFieldItem(_)
| ForeignFunctionItem(..) | ForeignFunctionItem(..)
@ -91,9 +91,10 @@ pub(crate) trait DocFolder: Sized {
| MacroItem(_) | MacroItem(_)
| ProcMacroItem(_) | ProcMacroItem(_)
| PrimitiveItem(_) | PrimitiveItem(_)
| TyAssocConstItem(..) | RequiredAssocConstItem(..)
| AssocConstItem(..) | ProvidedAssocConstItem(..)
| TyAssocTypeItem(..) | ImplAssocConstItem(..)
| RequiredAssocTypeItem(..)
| AssocTypeItem(..) | AssocTypeItem(..)
| KeywordItem => kind, | KeywordItem => kind,
} }

View file

@ -334,12 +334,13 @@ impl DocFolder for CacheBuilder<'_, '_> {
clean::ExternCrateItem { .. } clean::ExternCrateItem { .. }
| clean::ImportItem(..) | clean::ImportItem(..)
| clean::ImplItem(..) | clean::ImplItem(..)
| clean::TyMethodItem(..) | clean::RequiredMethodItem(..)
| clean::MethodItem(..) | clean::MethodItem(..)
| clean::StructFieldItem(..) | clean::StructFieldItem(..)
| clean::TyAssocConstItem(..) | clean::RequiredAssocConstItem(..)
| clean::AssocConstItem(..) | clean::ProvidedAssocConstItem(..)
| clean::TyAssocTypeItem(..) | clean::ImplAssocConstItem(..)
| clean::RequiredAssocTypeItem(..)
| clean::AssocTypeItem(..) | clean::AssocTypeItem(..)
| clean::StrippedItem(..) | clean::StrippedItem(..)
| clean::KeywordItem => { | clean::KeywordItem => {
@ -443,15 +444,17 @@ fn add_item_to_search_index(tcx: TyCtxt<'_>, cache: &mut Cache, item: &clean::It
let item_def_id = item.item_id.as_def_id().unwrap(); let item_def_id = item.item_id.as_def_id().unwrap();
let (parent_did, parent_path) = match item.kind { let (parent_did, parent_path) = match item.kind {
clean::StrippedItem(..) => return, clean::StrippedItem(..) => return,
clean::AssocConstItem(..) | clean::AssocTypeItem(..) clean::ProvidedAssocConstItem(..)
| clean::ImplAssocConstItem(..)
| clean::AssocTypeItem(..)
if cache.parent_stack.last().is_some_and(|parent| parent.is_trait_impl()) => if cache.parent_stack.last().is_some_and(|parent| parent.is_trait_impl()) =>
{ {
// skip associated items in trait impls // skip associated items in trait impls
return; return;
} }
clean::TyMethodItem(..) clean::RequiredMethodItem(..)
| clean::TyAssocConstItem(..) | clean::RequiredAssocConstItem(..)
| clean::TyAssocTypeItem(..) | clean::RequiredAssocTypeItem(..)
| clean::StructFieldItem(..) | clean::StructFieldItem(..)
| clean::VariantItem(..) => { | clean::VariantItem(..) => {
// Don't index if containing module is stripped (i.e., private), // Don't index if containing module is stripped (i.e., private),
@ -467,7 +470,10 @@ fn add_item_to_search_index(tcx: TyCtxt<'_>, cache: &mut Cache, item: &clean::It
let parent_path = &cache.stack[..cache.stack.len() - 1]; let parent_path = &cache.stack[..cache.stack.len() - 1];
(Some(parent_did), parent_path) (Some(parent_did), parent_path)
} }
clean::MethodItem(..) | clean::AssocConstItem(..) | clean::AssocTypeItem(..) => { clean::MethodItem(..)
| clean::ProvidedAssocConstItem(..)
| clean::ImplAssocConstItem(..)
| clean::AssocTypeItem(..) => {
let last = cache.parent_stack.last().expect("parent_stack is empty 2"); let last = cache.parent_stack.last().expect("parent_stack is empty 2");
let parent_did = match last { let parent_did = match last {
// impl Trait for &T { fn method(self); } // impl Trait for &T { fn method(self); }

View file

@ -88,7 +88,7 @@ impl<'a> From<&'a clean::Item> for ItemType {
clean::ConstantItem(..) => ItemType::Constant, clean::ConstantItem(..) => ItemType::Constant,
clean::TraitItem(..) => ItemType::Trait, clean::TraitItem(..) => ItemType::Trait,
clean::ImplItem(..) => ItemType::Impl, clean::ImplItem(..) => ItemType::Impl,
clean::TyMethodItem(..) => ItemType::TyMethod, clean::RequiredMethodItem(..) => ItemType::TyMethod,
clean::MethodItem(..) => ItemType::Method, clean::MethodItem(..) => ItemType::Method,
clean::StructFieldItem(..) => ItemType::StructField, clean::StructFieldItem(..) => ItemType::StructField,
clean::VariantItem(..) => ItemType::Variant, clean::VariantItem(..) => ItemType::Variant,
@ -96,8 +96,10 @@ impl<'a> From<&'a clean::Item> for ItemType {
clean::ForeignStaticItem(..) => ItemType::Static, // no ForeignStatic clean::ForeignStaticItem(..) => ItemType::Static, // no ForeignStatic
clean::MacroItem(..) => ItemType::Macro, clean::MacroItem(..) => ItemType::Macro,
clean::PrimitiveItem(..) => ItemType::Primitive, clean::PrimitiveItem(..) => ItemType::Primitive,
clean::TyAssocConstItem(..) | clean::AssocConstItem(..) => ItemType::AssocConst, clean::RequiredAssocConstItem(..)
clean::TyAssocTypeItem(..) | clean::AssocTypeItem(..) => ItemType::AssocType, | clean::ProvidedAssocConstItem(..)
| clean::ImplAssocConstItem(..) => ItemType::AssocConst,
clean::RequiredAssocTypeItem(..) | clean::AssocTypeItem(..) => ItemType::AssocType,
clean::ForeignTypeItem => ItemType::ForeignType, clean::ForeignTypeItem => ItemType::ForeignType,
clean::KeywordItem => ItemType::Keyword, clean::KeywordItem => ItemType::Keyword,
clean::TraitAliasItem(..) => ItemType::TraitAlias, clean::TraitAliasItem(..) => ItemType::TraitAlias,

View file

@ -836,12 +836,23 @@ fn assoc_href_attr(it: &clean::Item, link: AssocItemLink<'_>, cx: &Context<'_>)
href.map(|href| format!(" href=\"{href}\"")).unwrap_or_default() href.map(|href| format!(" href=\"{href}\"")).unwrap_or_default()
} }
#[derive(Debug)]
enum AssocConstValue<'a> {
// In trait definitions, it is relevant for the public API whether an
// associated constant comes with a default value, so even if we cannot
// render its value, the presence of a value must be shown using `= _`.
TraitDefault(&'a clean::ConstantKind),
// In impls, there is no need to show `= _`.
Impl(&'a clean::ConstantKind),
None,
}
fn assoc_const( fn assoc_const(
w: &mut Buffer, w: &mut Buffer,
it: &clean::Item, it: &clean::Item,
generics: &clean::Generics, generics: &clean::Generics,
ty: &clean::Type, ty: &clean::Type,
default: Option<&clean::ConstantKind>, value: AssocConstValue<'_>,
link: AssocItemLink<'_>, link: AssocItemLink<'_>,
indent: usize, indent: usize,
cx: &Context<'_>, cx: &Context<'_>,
@ -857,15 +868,20 @@ fn assoc_const(
generics = generics.print(cx), generics = generics.print(cx),
ty = ty.print(cx), ty = ty.print(cx),
); );
if let Some(default) = default { if let AssocConstValue::TraitDefault(konst) | AssocConstValue::Impl(konst) = value {
w.write_str(" = ");
// FIXME: `.value()` uses `clean::utils::format_integer_with_underscore_sep` under the // FIXME: `.value()` uses `clean::utils::format_integer_with_underscore_sep` under the
// hood which adds noisy underscores and a type suffix to number literals. // hood which adds noisy underscores and a type suffix to number literals.
// This hurts readability in this context especially when more complex expressions // This hurts readability in this context especially when more complex expressions
// are involved and it doesn't add much of value. // are involved and it doesn't add much of value.
// Find a way to print constants here without all that jazz. // Find a way to print constants here without all that jazz.
write!(w, "{}", Escape(&default.value(tcx).unwrap_or_else(|| default.expr(tcx)))); let repr = konst.value(tcx).unwrap_or_else(|| konst.expr(tcx));
if match value {
AssocConstValue::TraitDefault(_) => true, // always show
AssocConstValue::Impl(_) => repr != "_", // show if there is a meaningful value to show
AssocConstValue::None => unreachable!(),
} {
write!(w, " = {}", Escape(&repr));
}
} }
write!(w, "{}", print_where_clause(generics, cx, indent, Ending::NoNewline)); write!(w, "{}", print_where_clause(generics, cx, indent, Ending::NoNewline));
} }
@ -1076,33 +1092,43 @@ fn render_assoc_item(
) { ) {
match &item.kind { match &item.kind {
clean::StrippedItem(..) => {} clean::StrippedItem(..) => {}
clean::TyMethodItem(m) => { clean::RequiredMethodItem(m) => {
assoc_method(w, item, &m.generics, &m.decl, link, parent, cx, render_mode) assoc_method(w, item, &m.generics, &m.decl, link, parent, cx, render_mode)
} }
clean::MethodItem(m, _) => { clean::MethodItem(m, _) => {
assoc_method(w, item, &m.generics, &m.decl, link, parent, cx, render_mode) assoc_method(w, item, &m.generics, &m.decl, link, parent, cx, render_mode)
} }
clean::TyAssocConstItem(generics, ty) => assoc_const( clean::RequiredAssocConstItem(generics, ty) => assoc_const(
w, w,
item, item,
generics, generics,
ty, ty,
None, AssocConstValue::None,
link, link,
if parent == ItemType::Trait { 4 } else { 0 }, if parent == ItemType::Trait { 4 } else { 0 },
cx, cx,
), ),
clean::AssocConstItem(ci) => assoc_const( clean::ProvidedAssocConstItem(ci) => assoc_const(
w, w,
item, item,
&ci.generics, &ci.generics,
&ci.type_, &ci.type_,
Some(&ci.kind), AssocConstValue::TraitDefault(&ci.kind),
link, link,
if parent == ItemType::Trait { 4 } else { 0 }, if parent == ItemType::Trait { 4 } else { 0 },
cx, cx,
), ),
clean::TyAssocTypeItem(ref generics, ref bounds) => assoc_type( clean::ImplAssocConstItem(ci) => assoc_const(
w,
item,
&ci.generics,
&ci.type_,
AssocConstValue::Impl(&ci.kind),
link,
if parent == ItemType::Trait { 4 } else { 0 },
cx,
),
clean::RequiredAssocTypeItem(ref generics, ref bounds) => assoc_type(
w, w,
item, item,
generics, generics,
@ -1384,7 +1410,7 @@ fn render_deref_methods(
fn should_render_item(item: &clean::Item, deref_mut_: bool, tcx: TyCtxt<'_>) -> bool { fn should_render_item(item: &clean::Item, deref_mut_: bool, tcx: TyCtxt<'_>) -> bool {
let self_type_opt = match item.kind { let self_type_opt = match item.kind {
clean::MethodItem(ref method, _) => method.decl.receiver_type(), clean::MethodItem(ref method, _) => method.decl.receiver_type(),
clean::TyMethodItem(ref method) => method.decl.receiver_type(), clean::RequiredMethodItem(ref method) => method.decl.receiver_type(),
_ => None, _ => None,
}; };
@ -1660,7 +1686,7 @@ fn render_impl(
write!(w, "<details class=\"toggle{method_toggle_class}\" open><summary>"); write!(w, "<details class=\"toggle{method_toggle_class}\" open><summary>");
} }
match &item.kind { match &item.kind {
clean::MethodItem(..) | clean::TyMethodItem(_) => { clean::MethodItem(..) | clean::RequiredMethodItem(_) => {
// Only render when the method is not static or we allow static methods // Only render when the method is not static or we allow static methods
if render_method_item { if render_method_item {
let id = cx.derive_id(format!("{item_type}.{name}")); let id = cx.derive_id(format!("{item_type}.{name}"));
@ -1690,7 +1716,7 @@ fn render_impl(
w.write_str("</h4></section>"); w.write_str("</h4></section>");
} }
} }
clean::TyAssocConstItem(ref generics, ref ty) => { clean::RequiredAssocConstItem(ref generics, ref ty) => {
let source_id = format!("{item_type}.{name}"); let source_id = format!("{item_type}.{name}");
let id = cx.derive_id(&source_id); let id = cx.derive_id(&source_id);
write!(w, "<section id=\"{id}\" class=\"{item_type}{in_trait_class}\">"); write!(w, "<section id=\"{id}\" class=\"{item_type}{in_trait_class}\">");
@ -1705,14 +1731,14 @@ fn render_impl(
item, item,
generics, generics,
ty, ty,
None, AssocConstValue::None,
link.anchor(if trait_.is_some() { &source_id } else { &id }), link.anchor(if trait_.is_some() { &source_id } else { &id }),
0, 0,
cx, cx,
); );
w.write_str("</h4></section>"); w.write_str("</h4></section>");
} }
clean::AssocConstItem(ci) => { clean::ProvidedAssocConstItem(ci) | clean::ImplAssocConstItem(ci) => {
let source_id = format!("{item_type}.{name}"); let source_id = format!("{item_type}.{name}");
let id = cx.derive_id(&source_id); let id = cx.derive_id(&source_id);
write!(w, "<section id=\"{id}\" class=\"{item_type}{in_trait_class}\">"); write!(w, "<section id=\"{id}\" class=\"{item_type}{in_trait_class}\">");
@ -1727,14 +1753,18 @@ fn render_impl(
item, item,
&ci.generics, &ci.generics,
&ci.type_, &ci.type_,
Some(&ci.kind), match item.kind {
clean::ProvidedAssocConstItem(_) => AssocConstValue::TraitDefault(&ci.kind),
clean::ImplAssocConstItem(_) => AssocConstValue::Impl(&ci.kind),
_ => unreachable!(),
},
link.anchor(if trait_.is_some() { &source_id } else { &id }), link.anchor(if trait_.is_some() { &source_id } else { &id }),
0, 0,
cx, cx,
); );
w.write_str("</h4></section>"); w.write_str("</h4></section>");
} }
clean::TyAssocTypeItem(ref generics, ref bounds) => { clean::RequiredAssocTypeItem(ref generics, ref bounds) => {
let source_id = format!("{item_type}.{name}"); let source_id = format!("{item_type}.{name}");
let id = cx.derive_id(&source_id); let id = cx.derive_id(&source_id);
write!(w, "<section id=\"{id}\" class=\"{item_type}{in_trait_class}\">"); write!(w, "<section id=\"{id}\" class=\"{item_type}{in_trait_class}\">");
@ -1809,11 +1839,13 @@ fn render_impl(
if !impl_.is_negative_trait_impl() { if !impl_.is_negative_trait_impl() {
for trait_item in &impl_.items { for trait_item in &impl_.items {
match trait_item.kind { match trait_item.kind {
clean::MethodItem(..) | clean::TyMethodItem(_) => methods.push(trait_item), clean::MethodItem(..) | clean::RequiredMethodItem(_) => methods.push(trait_item),
clean::TyAssocTypeItem(..) | clean::AssocTypeItem(..) => { clean::RequiredAssocTypeItem(..) | clean::AssocTypeItem(..) => {
assoc_types.push(trait_item) assoc_types.push(trait_item)
} }
clean::TyAssocConstItem(..) | clean::AssocConstItem(_) => { clean::RequiredAssocConstItem(..)
| clean::ProvidedAssocConstItem(_)
| clean::ImplAssocConstItem(_) => {
// We render it directly since they're supposed to come first. // We render it directly since they're supposed to come first.
doc_impl_item( doc_impl_item(
&mut default_impl_items, &mut default_impl_items,

View file

@ -651,9 +651,11 @@ fn item_function(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, f: &clean::
fn item_trait(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Trait) { fn item_trait(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Trait) {
let tcx = cx.tcx(); let tcx = cx.tcx();
let bounds = bounds(&t.bounds, false, cx); let bounds = bounds(&t.bounds, false, cx);
let required_types = t.items.iter().filter(|m| m.is_ty_associated_type()).collect::<Vec<_>>(); let required_types =
t.items.iter().filter(|m| m.is_required_associated_type()).collect::<Vec<_>>();
let provided_types = t.items.iter().filter(|m| m.is_associated_type()).collect::<Vec<_>>(); let provided_types = t.items.iter().filter(|m| m.is_associated_type()).collect::<Vec<_>>();
let required_consts = t.items.iter().filter(|m| m.is_ty_associated_const()).collect::<Vec<_>>(); let required_consts =
t.items.iter().filter(|m| m.is_required_associated_const()).collect::<Vec<_>>();
let provided_consts = t.items.iter().filter(|m| m.is_associated_const()).collect::<Vec<_>>(); let provided_consts = t.items.iter().filter(|m| m.is_associated_const()).collect::<Vec<_>>();
let required_methods = t.items.iter().filter(|m| m.is_ty_method()).collect::<Vec<_>>(); let required_methods = t.items.iter().filter(|m| m.is_ty_method()).collect::<Vec<_>>();
let provided_methods = t.items.iter().filter(|m| m.is_method()).collect::<Vec<_>>(); let provided_methods = t.items.iter().filter(|m| m.is_method()).collect::<Vec<_>>();

View file

@ -837,7 +837,7 @@ pub(crate) fn get_function_type_for_search(
clean::ForeignFunctionItem(ref f, _) clean::ForeignFunctionItem(ref f, _)
| clean::FunctionItem(ref f) | clean::FunctionItem(ref f)
| clean::MethodItem(ref f, _) | clean::MethodItem(ref f, _)
| clean::TyMethodItem(ref f) => { | clean::RequiredMethodItem(ref f) => {
get_fn_inputs_and_outputs(f, tcx, impl_or_trait_generics, cache) get_fn_inputs_and_outputs(f, tcx, impl_or_trait_generics, cache)
} }
_ => return None, _ => return None,
@ -1207,10 +1207,11 @@ fn simplify_fn_type<'a, 'tcx>(
&& let Type::Path { path } = arg && let Type::Path { path } = arg
&& let def_id = path.def_id() && let def_id = path.def_id()
&& let Some(trait_) = cache.traits.get(&def_id) && let Some(trait_) = cache.traits.get(&def_id)
&& trait_.items.iter().any(|at| at.is_ty_associated_type()) && trait_.items.iter().any(|at| at.is_required_associated_type())
{ {
for assoc_ty in &trait_.items { for assoc_ty in &trait_.items {
if let clean::ItemKind::TyAssocTypeItem(_generics, bounds) = &assoc_ty.kind if let clean::ItemKind::RequiredAssocTypeItem(_generics, bounds) =
&assoc_ty.kind
&& let Some(name) = assoc_ty.name && let Some(name) = assoc_ty.name
{ {
let idx = -isize::try_from(rgen.len() + 1).unwrap(); let idx = -isize::try_from(rgen.len() + 1).unwrap();

View file

@ -282,10 +282,10 @@ fn sidebar_trait<'a>(
res res
} }
let req_assoc = filter_items(&t.items, |m| m.is_ty_associated_type(), "associatedtype"); let req_assoc = filter_items(&t.items, |m| m.is_required_associated_type(), "associatedtype");
let prov_assoc = filter_items(&t.items, |m| m.is_associated_type(), "associatedtype"); let prov_assoc = filter_items(&t.items, |m| m.is_associated_type(), "associatedtype");
let req_assoc_const = let req_assoc_const =
filter_items(&t.items, |m| m.is_ty_associated_const(), "associatedconstant"); filter_items(&t.items, |m| m.is_required_associated_const(), "associatedconstant");
let prov_assoc_const = let prov_assoc_const =
filter_items(&t.items, |m| m.is_associated_const(), "associatedconstant"); filter_items(&t.items, |m| m.is_associated_const(), "associatedconstant");
let req_method = filter_items(&t.items, |m| m.is_ty_method(), "tymethod"); let req_method = filter_items(&t.items, |m| m.is_ty_method(), "tymethod");

View file

@ -319,7 +319,9 @@ fn from_clean_item(item: clean::Item, renderer: &JsonRenderer<'_>) -> ItemEnum {
TraitItem(t) => ItemEnum::Trait((*t).into_json(renderer)), TraitItem(t) => ItemEnum::Trait((*t).into_json(renderer)),
TraitAliasItem(t) => ItemEnum::TraitAlias(t.into_json(renderer)), TraitAliasItem(t) => ItemEnum::TraitAlias(t.into_json(renderer)),
MethodItem(m, _) => ItemEnum::Function(from_function(m, true, header.unwrap(), renderer)), MethodItem(m, _) => ItemEnum::Function(from_function(m, true, header.unwrap(), renderer)),
TyMethodItem(m) => ItemEnum::Function(from_function(m, false, header.unwrap(), renderer)), RequiredMethodItem(m) => {
ItemEnum::Function(from_function(m, false, header.unwrap(), renderer))
}
ImplItem(i) => ItemEnum::Impl((*i).into_json(renderer)), ImplItem(i) => ItemEnum::Impl((*i).into_json(renderer)),
StaticItem(s) => ItemEnum::Static(convert_static(s, rustc_hir::Safety::Safe, renderer)), StaticItem(s) => ItemEnum::Static(convert_static(s, rustc_hir::Safety::Safe, renderer)),
ForeignStaticItem(s, safety) => ItemEnum::Static(convert_static(s, safety, renderer)), ForeignStaticItem(s, safety) => ItemEnum::Static(convert_static(s, safety, renderer)),
@ -339,15 +341,15 @@ fn from_clean_item(item: clean::Item, renderer: &JsonRenderer<'_>) -> ItemEnum {
}) })
} }
// FIXME(generic_const_items): Add support for generic associated consts. // FIXME(generic_const_items): Add support for generic associated consts.
TyAssocConstItem(_generics, ty) => { RequiredAssocConstItem(_generics, ty) => {
ItemEnum::AssocConst { type_: (*ty).into_json(renderer), value: None } ItemEnum::AssocConst { type_: (*ty).into_json(renderer), value: None }
} }
// FIXME(generic_const_items): Add support for generic associated consts. // FIXME(generic_const_items): Add support for generic associated consts.
AssocConstItem(ci) => ItemEnum::AssocConst { ProvidedAssocConstItem(ci) | ImplAssocConstItem(ci) => ItemEnum::AssocConst {
type_: ci.type_.into_json(renderer), type_: ci.type_.into_json(renderer),
value: Some(ci.kind.expr(renderer.tcx)), value: Some(ci.kind.expr(renderer.tcx)),
}, },
TyAssocTypeItem(g, b) => ItemEnum::AssocType { RequiredAssocTypeItem(g, b) => ItemEnum::AssocType {
generics: g.into_json(renderer), generics: g.into_json(renderer),
bounds: b.into_json(renderer), bounds: b.into_json(renderer),
type_: None, type_: None,

View file

@ -72,10 +72,11 @@ pub(crate) fn should_have_doc_example(cx: &DocContext<'_>, item: &clean::Item) -
| clean::ForeignFunctionItem(..) | clean::ForeignFunctionItem(..)
| clean::ForeignStaticItem(..) | clean::ForeignStaticItem(..)
| clean::ForeignTypeItem | clean::ForeignTypeItem
| clean::AssocConstItem(..)
| clean::AssocTypeItem(..) | clean::AssocTypeItem(..)
| clean::TyAssocConstItem(..) | clean::RequiredAssocConstItem(..)
| clean::TyAssocTypeItem(..) | clean::ProvidedAssocConstItem(..)
| clean::ImplAssocConstItem(..)
| clean::RequiredAssocTypeItem(..)
// check for trait impl // check for trait impl
| clean::ImplItem(box clean::Impl { trait_: Some(_), .. }) | clean::ImplItem(box clean::Impl { trait_: Some(_), .. })
) )

View file

@ -67,11 +67,12 @@ impl DocFolder for StabilityPropagator<'_, '_> {
// Don't inherit the parent's stability for these items, because they // Don't inherit the parent's stability for these items, because they
// are potentially accessible even if the parent is more unstable. // are potentially accessible even if the parent is more unstable.
ItemKind::ImplItem(..) ItemKind::ImplItem(..)
| ItemKind::TyMethodItem(..) | ItemKind::RequiredMethodItem(..)
| ItemKind::MethodItem(..) | ItemKind::MethodItem(..)
| ItemKind::TyAssocConstItem(..) | ItemKind::RequiredAssocConstItem(..)
| ItemKind::AssocConstItem(..) | ItemKind::ProvidedAssocConstItem(..)
| ItemKind::TyAssocTypeItem(..) | ItemKind::ImplAssocConstItem(..)
| ItemKind::RequiredAssocTypeItem(..)
| ItemKind::AssocTypeItem(..) | ItemKind::AssocTypeItem(..)
| ItemKind::PrimitiveItem(..) | ItemKind::PrimitiveItem(..)
| ItemKind::KeywordItem => own_stability, | ItemKind::KeywordItem => own_stability,

View file

@ -79,7 +79,10 @@ impl DocFolder for Stripper<'_, '_> {
} }
} }
clean::MethodItem(..) | clean::AssocConstItem(..) | clean::AssocTypeItem(..) => { clean::MethodItem(..)
| clean::ProvidedAssocConstItem(..)
| clean::ImplAssocConstItem(..)
| clean::AssocTypeItem(..) => {
let item_id = i.item_id; let item_id = i.item_id;
if item_id.is_local() if item_id.is_local()
&& !self.effective_visibilities.is_reachable(self.tcx, item_id.expect_def_id()) && !self.effective_visibilities.is_reachable(self.tcx, item_id.expect_def_id())
@ -118,7 +121,9 @@ impl DocFolder for Stripper<'_, '_> {
clean::ImplItem(..) => {} clean::ImplItem(..) => {}
// tymethods etc. have no control over privacy // tymethods etc. have no control over privacy
clean::TyMethodItem(..) | clean::TyAssocConstItem(..) | clean::TyAssocTypeItem(..) => {} clean::RequiredMethodItem(..)
| clean::RequiredAssocConstItem(..)
| clean::RequiredAssocTypeItem(..) => {}
// Proc-macros are always public // Proc-macros are always public
clean::ProcMacroItem(..) => {} clean::ProcMacroItem(..) => {}

View file

@ -35,7 +35,7 @@ pub(crate) trait DocVisitor<'a>: Sized {
| StaticItem(_) | StaticItem(_)
| ConstantItem(..) | ConstantItem(..)
| TraitAliasItem(_) | TraitAliasItem(_)
| TyMethodItem(_) | RequiredMethodItem(_)
| MethodItem(_, _) | MethodItem(_, _)
| StructFieldItem(_) | StructFieldItem(_)
| ForeignFunctionItem(..) | ForeignFunctionItem(..)
@ -44,9 +44,10 @@ pub(crate) trait DocVisitor<'a>: Sized {
| MacroItem(_) | MacroItem(_)
| ProcMacroItem(_) | ProcMacroItem(_)
| PrimitiveItem(_) | PrimitiveItem(_)
| TyAssocConstItem(..) | RequiredAssocConstItem(..)
| AssocConstItem(..) | ProvidedAssocConstItem(..)
| TyAssocTypeItem(..) | ImplAssocConstItem(..)
| RequiredAssocTypeItem(..)
| AssocTypeItem(..) | AssocTypeItem(..)
| KeywordItem => {} | KeywordItem => {}
} }

View file

@ -19,6 +19,7 @@ use rustc_middle::ty::layout::{FnAbiOf, LayoutOf, MaybeResult, TyAndLayout};
use rustc_middle::ty::{self, FloatTy, IntTy, Ty, TyCtxt, UintTy}; use rustc_middle::ty::{self, FloatTy, IntTy, Ty, TyCtxt, UintTy};
use rustc_session::config::CrateType; use rustc_session::config::CrateType;
use rustc_span::{Span, Symbol}; use rustc_span::{Span, Symbol};
use rustc_target::callconv::{Conv, FnAbi};
use crate::*; use crate::*;
@ -914,13 +915,11 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
} }
/// Check that the ABI is what we expect. /// Check that the ABI is what we expect.
fn check_abi<'a>(&self, abi: ExternAbi, exp_abi: ExternAbi) -> InterpResult<'a, ()> { fn check_abi<'a>(&self, fn_abi: &FnAbi<'tcx, Ty<'tcx>>, exp_abi: Conv) -> InterpResult<'a, ()> {
if abi != exp_abi { if fn_abi.conv != exp_abi {
throw_ub_format!( throw_ub_format!(
"calling a function with ABI {} using caller ABI {}", "calling a function with ABI {:?} using caller ABI {:?}",
exp_abi.name(), exp_abi, fn_abi.conv);
abi.name()
)
} }
interp_ok(()) interp_ok(())
} }
@ -950,8 +949,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
fn check_abi_and_shim_symbol_clash( fn check_abi_and_shim_symbol_clash(
&mut self, &mut self,
abi: ExternAbi, abi: &FnAbi<'tcx, Ty<'tcx>>,
exp_abi: ExternAbi, exp_abi: Conv,
link_name: Symbol, link_name: Symbol,
) -> InterpResult<'tcx, ()> { ) -> InterpResult<'tcx, ()> {
self.check_abi(abi, exp_abi)?; self.check_abi(abi, exp_abi)?;
@ -975,8 +974,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
fn check_shim<'a, const N: usize>( fn check_shim<'a, const N: usize>(
&mut self, &mut self,
abi: ExternAbi, abi: &FnAbi<'tcx, Ty<'tcx>>,
exp_abi: ExternAbi, exp_abi: Conv,
link_name: Symbol, link_name: Symbol,
args: &'a [OpTy<'tcx>], args: &'a [OpTy<'tcx>],
) -> InterpResult<'tcx, &'a [OpTy<'tcx>; N]> ) -> InterpResult<'tcx, &'a [OpTy<'tcx>; N]>

View file

@ -13,6 +13,7 @@ use rand::{Rng, SeedableRng};
use rustc_abi::{Align, ExternAbi, Size}; use rustc_abi::{Align, ExternAbi, Size};
use rustc_attr_parsing::InlineAttr; use rustc_attr_parsing::InlineAttr;
use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_target::callconv::FnAbi;
#[allow(unused)] #[allow(unused)]
use rustc_data_structures::static_assert_size; use rustc_data_structures::static_assert_size;
use rustc_middle::mir; use rustc_middle::mir;
@ -1010,7 +1011,7 @@ impl<'tcx> Machine<'tcx> for MiriMachine<'tcx> {
fn find_mir_or_eval_fn( fn find_mir_or_eval_fn(
ecx: &mut MiriInterpCx<'tcx>, ecx: &mut MiriInterpCx<'tcx>,
instance: ty::Instance<'tcx>, instance: ty::Instance<'tcx>,
abi: ExternAbi, abi: &FnAbi<'tcx, Ty<'tcx>>,
args: &[FnArg<'tcx, Provenance>], args: &[FnArg<'tcx, Provenance>],
dest: &MPlaceTy<'tcx>, dest: &MPlaceTy<'tcx>,
ret: Option<mir::BasicBlock>, ret: Option<mir::BasicBlock>,
@ -1037,7 +1038,7 @@ impl<'tcx> Machine<'tcx> for MiriMachine<'tcx> {
fn call_extra_fn( fn call_extra_fn(
ecx: &mut MiriInterpCx<'tcx>, ecx: &mut MiriInterpCx<'tcx>,
fn_val: DynSym, fn_val: DynSym,
abi: ExternAbi, abi: &FnAbi<'tcx, Ty<'tcx>>,
args: &[FnArg<'tcx, Provenance>], args: &[FnArg<'tcx, Provenance>],
dest: &MPlaceTy<'tcx>, dest: &MPlaceTy<'tcx>,
ret: Option<mir::BasicBlock>, ret: Option<mir::BasicBlock>,

View file

@ -1,7 +1,8 @@
use rustc_abi::{ExternAbi, Size}; use rustc_abi::Size;
use rustc_middle::ty::layout::LayoutOf as _; use rustc_middle::ty::layout::LayoutOf as _;
use rustc_middle::ty::{self, Instance, Ty}; use rustc_middle::ty::{self, Instance, Ty};
use rustc_span::{BytePos, Loc, Symbol, hygiene}; use rustc_span::{BytePos, Loc, Symbol, hygiene};
use rustc_target::callconv::{Conv, FnAbi};
use crate::helpers::check_min_arg_count; use crate::helpers::check_min_arg_count;
use crate::*; use crate::*;
@ -10,13 +11,13 @@ impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {}
pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
fn handle_miri_backtrace_size( fn handle_miri_backtrace_size(
&mut self, &mut self,
abi: ExternAbi, abi: &FnAbi<'tcx, Ty<'tcx>>,
link_name: Symbol, link_name: Symbol,
args: &[OpTy<'tcx>], args: &[OpTy<'tcx>],
dest: &MPlaceTy<'tcx>, dest: &MPlaceTy<'tcx>,
) -> InterpResult<'tcx> { ) -> InterpResult<'tcx> {
let this = self.eval_context_mut(); let this = self.eval_context_mut();
let [flags] = this.check_shim(abi, ExternAbi::Rust, link_name, args)?; let [flags] = this.check_shim(abi, Conv::Rust, link_name, args)?;
let flags = this.read_scalar(flags)?.to_u64()?; let flags = this.read_scalar(flags)?.to_u64()?;
if flags != 0 { if flags != 0 {
@ -30,7 +31,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
fn handle_miri_get_backtrace( fn handle_miri_get_backtrace(
&mut self, &mut self,
abi: ExternAbi, abi: &FnAbi<'tcx, Ty<'tcx>>,
link_name: Symbol, link_name: Symbol,
args: &[OpTy<'tcx>], args: &[OpTy<'tcx>],
dest: &MPlaceTy<'tcx>, dest: &MPlaceTy<'tcx>,
@ -71,7 +72,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
// storage for pointers is allocated by miri // storage for pointers is allocated by miri
// deallocating the slice is undefined behavior with a custom global allocator // deallocating the slice is undefined behavior with a custom global allocator
0 => { 0 => {
let [_flags] = this.check_shim(abi, ExternAbi::Rust, link_name, args)?; let [_flags] = this.check_shim(abi, Conv::Rust, link_name, args)?;
let alloc = this.allocate(array_layout, MiriMemoryKind::Rust.into())?; let alloc = this.allocate(array_layout, MiriMemoryKind::Rust.into())?;
@ -86,7 +87,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
} }
// storage for pointers is allocated by the caller // storage for pointers is allocated by the caller
1 => { 1 => {
let [_flags, buf] = this.check_shim(abi, ExternAbi::Rust, link_name, args)?; let [_flags, buf] = this.check_shim(abi, Conv::Rust, link_name, args)?;
let buf_place = this.deref_pointer(buf)?; let buf_place = this.deref_pointer(buf)?;
@ -136,13 +137,13 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
fn handle_miri_resolve_frame( fn handle_miri_resolve_frame(
&mut self, &mut self,
abi: ExternAbi, abi: &FnAbi<'tcx, Ty<'tcx>>,
link_name: Symbol, link_name: Symbol,
args: &[OpTy<'tcx>], args: &[OpTy<'tcx>],
dest: &MPlaceTy<'tcx>, dest: &MPlaceTy<'tcx>,
) -> InterpResult<'tcx> { ) -> InterpResult<'tcx> {
let this = self.eval_context_mut(); let this = self.eval_context_mut();
let [ptr, flags] = this.check_shim(abi, ExternAbi::Rust, link_name, args)?; let [ptr, flags] = this.check_shim(abi, Conv::Rust, link_name, args)?;
let flags = this.read_scalar(flags)?.to_u64()?; let flags = this.read_scalar(flags)?.to_u64()?;
@ -207,14 +208,14 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
fn handle_miri_resolve_frame_names( fn handle_miri_resolve_frame_names(
&mut self, &mut self,
abi: ExternAbi, abi: &FnAbi<'tcx, Ty<'tcx>>,
link_name: Symbol, link_name: Symbol,
args: &[OpTy<'tcx>], args: &[OpTy<'tcx>],
) -> InterpResult<'tcx> { ) -> InterpResult<'tcx> {
let this = self.eval_context_mut(); let this = self.eval_context_mut();
let [ptr, flags, name_ptr, filename_ptr] = let [ptr, flags, name_ptr, filename_ptr] =
this.check_shim(abi, ExternAbi::Rust, link_name, args)?; this.check_shim(abi, Conv::Rust, link_name, args)?;
let flags = this.read_scalar(flags)?.to_u64()?; let flags = this.read_scalar(flags)?.to_u64()?;
if flags != 0 { if flags != 0 {

View file

@ -3,14 +3,17 @@ use std::io::Write;
use std::iter; use std::iter;
use std::path::Path; use std::path::Path;
use rustc_abi::{Align, AlignFromBytesError, ExternAbi, Size}; use rustc_abi::{Align, AlignFromBytesError, Size};
use rustc_apfloat::Float; use rustc_apfloat::Float;
use rustc_ast::expand::allocator::alloc_error_handler_name; use rustc_ast::expand::allocator::alloc_error_handler_name;
use rustc_hir::def::DefKind; use rustc_hir::def::DefKind;
use rustc_hir::def_id::CrateNum; use rustc_hir::def_id::CrateNum;
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
use rustc_middle::{mir, ty}; use rustc_middle::{mir, ty};
use rustc_middle::ty::Ty;
use rustc_span::Symbol; use rustc_span::Symbol;
use rustc_target::callconv::{Conv, FnAbi};
use self::helpers::{ToHost, ToSoft}; use self::helpers::{ToHost, ToSoft};
use super::alloc::EvalContextExt as _; use super::alloc::EvalContextExt as _;
@ -39,7 +42,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
fn emulate_foreign_item( fn emulate_foreign_item(
&mut self, &mut self,
link_name: Symbol, link_name: Symbol,
abi: ExternAbi, abi: &FnAbi<'tcx, Ty<'tcx>>,
args: &[OpTy<'tcx>], args: &[OpTy<'tcx>],
dest: &MPlaceTy<'tcx>, dest: &MPlaceTy<'tcx>,
ret: Option<mir::BasicBlock>, ret: Option<mir::BasicBlock>,
@ -106,7 +109,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
fn emulate_dyn_sym( fn emulate_dyn_sym(
&mut self, &mut self,
sym: DynSym, sym: DynSym,
abi: ExternAbi, abi: &FnAbi<'tcx, Ty<'tcx>>,
args: &[OpTy<'tcx>], args: &[OpTy<'tcx>],
dest: &MPlaceTy<'tcx>, dest: &MPlaceTy<'tcx>,
ret: Option<mir::BasicBlock>, ret: Option<mir::BasicBlock>,
@ -218,7 +221,7 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
fn emulate_foreign_item_inner( fn emulate_foreign_item_inner(
&mut self, &mut self,
link_name: Symbol, link_name: Symbol,
abi: ExternAbi, abi: &FnAbi<'tcx, Ty<'tcx>>,
args: &[OpTy<'tcx>], args: &[OpTy<'tcx>],
dest: &MPlaceTy<'tcx>, dest: &MPlaceTy<'tcx>,
) -> InterpResult<'tcx, EmulateItemResult> { ) -> InterpResult<'tcx, EmulateItemResult> {
@ -235,11 +238,10 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
return interp_ok(EmulateItemResult::NeedsReturn); return interp_ok(EmulateItemResult::NeedsReturn);
} }
} }
// When adding a new shim, you should follow the following pattern: // When adding a new shim, you should follow the following pattern:
// ``` // ```
// "shim_name" => { // "shim_name" => {
// let [arg1, arg2, arg3] = this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; // let [arg1, arg2, arg3] = this.check_shim(abi, Conv::::C , link_name, args)?;
// let result = this.shim_name(arg1, arg2, arg3)?; // let result = this.shim_name(arg1, arg2, arg3)?;
// this.write_scalar(result, dest)?; // this.write_scalar(result, dest)?;
// } // }
@ -277,16 +279,16 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
match link_name.as_str() { match link_name.as_str() {
// Miri-specific extern functions // Miri-specific extern functions
"miri_start_unwind" => { "miri_start_unwind" => {
let [payload] = this.check_shim(abi, ExternAbi::Rust, link_name, args)?; let [payload] = this.check_shim(abi, Conv::Rust, link_name, args)?;
this.handle_miri_start_unwind(payload)?; this.handle_miri_start_unwind(payload)?;
return interp_ok(EmulateItemResult::NeedsUnwind); return interp_ok(EmulateItemResult::NeedsUnwind);
} }
"miri_run_provenance_gc" => { "miri_run_provenance_gc" => {
let [] = this.check_shim(abi, ExternAbi::Rust, link_name, args)?; let [] = this.check_shim(abi, Conv::Rust, link_name, args)?;
this.run_provenance_gc(); this.run_provenance_gc();
} }
"miri_get_alloc_id" => { "miri_get_alloc_id" => {
let [ptr] = this.check_shim(abi, ExternAbi::Rust, link_name, args)?; let [ptr] = this.check_shim(abi, Conv::Rust, link_name, args)?;
let ptr = this.read_pointer(ptr)?; let ptr = this.read_pointer(ptr)?;
let (alloc_id, _, _) = this.ptr_get_alloc_id(ptr, 0).map_err_kind(|_e| { let (alloc_id, _, _) = this.ptr_get_alloc_id(ptr, 0).map_err_kind(|_e| {
err_machine_stop!(TerminationInfo::Abort(format!( err_machine_stop!(TerminationInfo::Abort(format!(
@ -296,7 +298,7 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
this.write_scalar(Scalar::from_u64(alloc_id.0.get()), dest)?; this.write_scalar(Scalar::from_u64(alloc_id.0.get()), dest)?;
} }
"miri_print_borrow_state" => { "miri_print_borrow_state" => {
let [id, show_unnamed] = this.check_shim(abi, ExternAbi::Rust, link_name, args)?; let [id, show_unnamed] = this.check_shim(abi, Conv::Rust, link_name, args)?;
let id = this.read_scalar(id)?.to_u64()?; let id = this.read_scalar(id)?.to_u64()?;
let show_unnamed = this.read_scalar(show_unnamed)?.to_bool()?; let show_unnamed = this.read_scalar(show_unnamed)?.to_bool()?;
if let Some(id) = std::num::NonZero::new(id).map(AllocId) if let Some(id) = std::num::NonZero::new(id).map(AllocId)
@ -311,7 +313,7 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
// This associates a name to a tag. Very useful for debugging, and also makes // This associates a name to a tag. Very useful for debugging, and also makes
// tests more strict. // tests more strict.
let [ptr, nth_parent, name] = let [ptr, nth_parent, name] =
this.check_shim(abi, ExternAbi::Rust, link_name, args)?; this.check_shim(abi, Conv::Rust, link_name, args)?;
let ptr = this.read_pointer(ptr)?; let ptr = this.read_pointer(ptr)?;
let nth_parent = this.read_scalar(nth_parent)?.to_u8()?; let nth_parent = this.read_scalar(nth_parent)?.to_u8()?;
let name = this.read_immediate(name)?; let name = this.read_immediate(name)?;
@ -324,7 +326,7 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
this.give_pointer_debug_name(ptr, nth_parent, &name)?; this.give_pointer_debug_name(ptr, nth_parent, &name)?;
} }
"miri_static_root" => { "miri_static_root" => {
let [ptr] = this.check_shim(abi, ExternAbi::Rust, link_name, args)?; let [ptr] = this.check_shim(abi, Conv::Rust, link_name, args)?;
let ptr = this.read_pointer(ptr)?; let ptr = this.read_pointer(ptr)?;
let (alloc_id, offset, _) = this.ptr_get_alloc_id(ptr, 0)?; let (alloc_id, offset, _) = this.ptr_get_alloc_id(ptr, 0)?;
if offset != Size::ZERO { if offset != Size::ZERO {
@ -336,7 +338,7 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
} }
"miri_host_to_target_path" => { "miri_host_to_target_path" => {
let [ptr, out, out_size] = let [ptr, out, out_size] =
this.check_shim(abi, ExternAbi::Rust, link_name, args)?; this.check_shim(abi, Conv::Rust, link_name, args)?;
let ptr = this.read_pointer(ptr)?; let ptr = this.read_pointer(ptr)?;
let out = this.read_pointer(out)?; let out = this.read_pointer(out)?;
let out_size = this.read_scalar(out_size)?.to_target_usize(this)?; let out_size = this.read_scalar(out_size)?.to_target_usize(this)?;
@ -372,7 +374,7 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
// Writes some bytes to the interpreter's stdout/stderr. See the // Writes some bytes to the interpreter's stdout/stderr. See the
// README for details. // README for details.
"miri_write_to_stdout" | "miri_write_to_stderr" => { "miri_write_to_stdout" | "miri_write_to_stderr" => {
let [msg] = this.check_shim(abi, ExternAbi::Rust, link_name, args)?; let [msg] = this.check_shim(abi, Conv::Rust, link_name, args)?;
let msg = this.read_immediate(msg)?; let msg = this.read_immediate(msg)?;
let msg = this.read_byte_slice(&msg)?; let msg = this.read_byte_slice(&msg)?;
// Note: we're ignoring errors writing to host stdout/stderr. // Note: we're ignoring errors writing to host stdout/stderr.
@ -386,7 +388,7 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
"miri_promise_symbolic_alignment" => { "miri_promise_symbolic_alignment" => {
use rustc_abi::AlignFromBytesError; use rustc_abi::AlignFromBytesError;
let [ptr, align] = this.check_shim(abi, ExternAbi::Rust, link_name, args)?; let [ptr, align] = this.check_shim(abi, Conv::Rust, link_name, args)?;
let ptr = this.read_pointer(ptr)?; let ptr = this.read_pointer(ptr)?;
let align = this.read_target_usize(align)?; let align = this.read_target_usize(align)?;
if !align.is_power_of_two() { if !align.is_power_of_two() {
@ -428,12 +430,12 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
// Aborting the process. // Aborting the process.
"exit" => { "exit" => {
let [code] = let [code] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C , link_name, args)?;
let code = this.read_scalar(code)?.to_i32()?; let code = this.read_scalar(code)?.to_i32()?;
throw_machine_stop!(TerminationInfo::Exit { code: code.into(), leak_check: false }); throw_machine_stop!(TerminationInfo::Exit { code: code.into(), leak_check: false });
} }
"abort" => { "abort" => {
let [] = this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; let [] = this.check_shim(abi, Conv::C , link_name, args)?;
throw_machine_stop!(TerminationInfo::Abort( throw_machine_stop!(TerminationInfo::Abort(
"the program aborted execution".to_owned() "the program aborted execution".to_owned()
)) ))
@ -442,7 +444,7 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
// Standard C allocation // Standard C allocation
"malloc" => { "malloc" => {
let [size] = let [size] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C , link_name, args)?;
let size = this.read_target_usize(size)?; let size = this.read_target_usize(size)?;
if size <= this.max_size_of_val().bytes() { if size <= this.max_size_of_val().bytes() {
let res = this.malloc(size, /*zero_init:*/ false)?; let res = this.malloc(size, /*zero_init:*/ false)?;
@ -457,7 +459,7 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
} }
"calloc" => { "calloc" => {
let [items, elem_size] = let [items, elem_size] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C , link_name, args)?;
let items = this.read_target_usize(items)?; let items = this.read_target_usize(items)?;
let elem_size = this.read_target_usize(elem_size)?; let elem_size = this.read_target_usize(elem_size)?;
if let Some(size) = this.compute_size_in_bytes(Size::from_bytes(elem_size), items) { if let Some(size) = this.compute_size_in_bytes(Size::from_bytes(elem_size), items) {
@ -473,13 +475,13 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
} }
"free" => { "free" => {
let [ptr] = let [ptr] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C , link_name, args)?;
let ptr = this.read_pointer(ptr)?; let ptr = this.read_pointer(ptr)?;
this.free(ptr)?; this.free(ptr)?;
} }
"realloc" => { "realloc" => {
let [old_ptr, new_size] = let [old_ptr, new_size] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C , link_name, args)?;
let old_ptr = this.read_pointer(old_ptr)?; let old_ptr = this.read_pointer(old_ptr)?;
let new_size = this.read_target_usize(new_size)?; let new_size = this.read_target_usize(new_size)?;
if new_size <= this.max_size_of_val().bytes() { if new_size <= this.max_size_of_val().bytes() {
@ -499,7 +501,7 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
let default = |ecx: &mut MiriInterpCx<'tcx>| { let default = |ecx: &mut MiriInterpCx<'tcx>| {
// Only call `check_shim` when `#[global_allocator]` isn't used. When that // Only call `check_shim` when `#[global_allocator]` isn't used. When that
// macro is used, we act like no shim exists, so that the exported function can run. // macro is used, we act like no shim exists, so that the exported function can run.
let [size, align] = ecx.check_shim(abi, ExternAbi::Rust, link_name, args)?; let [size, align] = ecx.check_shim(abi, Conv::Rust, link_name, args)?;
let size = ecx.read_target_usize(size)?; let size = ecx.read_target_usize(size)?;
let align = ecx.read_target_usize(align)?; let align = ecx.read_target_usize(align)?;
@ -533,7 +535,7 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
return this.emulate_allocator(|this| { return this.emulate_allocator(|this| {
// See the comment for `__rust_alloc` why `check_shim` is only called in the // See the comment for `__rust_alloc` why `check_shim` is only called in the
// default case. // default case.
let [size, align] = this.check_shim(abi, ExternAbi::Rust, link_name, args)?; let [size, align] = this.check_shim(abi, Conv::Rust, link_name, args)?;
let size = this.read_target_usize(size)?; let size = this.read_target_usize(size)?;
let align = this.read_target_usize(align)?; let align = this.read_target_usize(align)?;
@ -559,7 +561,7 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
// See the comment for `__rust_alloc` why `check_shim` is only called in the // See the comment for `__rust_alloc` why `check_shim` is only called in the
// default case. // default case.
let [ptr, old_size, align] = let [ptr, old_size, align] =
ecx.check_shim(abi, ExternAbi::Rust, link_name, args)?; ecx.check_shim(abi, Conv::Rust, link_name, args)?;
let ptr = ecx.read_pointer(ptr)?; let ptr = ecx.read_pointer(ptr)?;
let old_size = ecx.read_target_usize(old_size)?; let old_size = ecx.read_target_usize(old_size)?;
let align = ecx.read_target_usize(align)?; let align = ecx.read_target_usize(align)?;
@ -594,7 +596,7 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
// See the comment for `__rust_alloc` why `check_shim` is only called in the // See the comment for `__rust_alloc` why `check_shim` is only called in the
// default case. // default case.
let [ptr, old_size, align, new_size] = let [ptr, old_size, align, new_size] =
this.check_shim(abi, ExternAbi::Rust, link_name, args)?; this.check_shim(abi, Conv::Rust, link_name, args)?;
let ptr = this.read_pointer(ptr)?; let ptr = this.read_pointer(ptr)?;
let old_size = this.read_target_usize(old_size)?; let old_size = this.read_target_usize(old_size)?;
let align = this.read_target_usize(align)?; let align = this.read_target_usize(align)?;
@ -618,7 +620,7 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
// C memory handling functions // C memory handling functions
"memcmp" => { "memcmp" => {
let [left, right, n] = let [left, right, n] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C , link_name, args)?;
let left = this.read_pointer(left)?; let left = this.read_pointer(left)?;
let right = this.read_pointer(right)?; let right = this.read_pointer(right)?;
let n = Size::from_bytes(this.read_target_usize(n)?); let n = Size::from_bytes(this.read_target_usize(n)?);
@ -643,7 +645,7 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
} }
"memrchr" => { "memrchr" => {
let [ptr, val, num] = let [ptr, val, num] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C , link_name, args)?;
let ptr = this.read_pointer(ptr)?; let ptr = this.read_pointer(ptr)?;
let val = this.read_scalar(val)?.to_i32()?; let val = this.read_scalar(val)?.to_i32()?;
let num = this.read_target_usize(num)?; let num = this.read_target_usize(num)?;
@ -670,7 +672,7 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
} }
"memchr" => { "memchr" => {
let [ptr, val, num] = let [ptr, val, num] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C , link_name, args)?;
let ptr = this.read_pointer(ptr)?; let ptr = this.read_pointer(ptr)?;
let val = this.read_scalar(val)?.to_i32()?; let val = this.read_scalar(val)?.to_i32()?;
let num = this.read_target_usize(num)?; let num = this.read_target_usize(num)?;
@ -694,7 +696,7 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
} }
"strlen" => { "strlen" => {
let [ptr] = let [ptr] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C , link_name, args)?;
let ptr = this.read_pointer(ptr)?; let ptr = this.read_pointer(ptr)?;
// This reads at least 1 byte, so we are already enforcing that this is a valid pointer. // This reads at least 1 byte, so we are already enforcing that this is a valid pointer.
let n = this.read_c_str(ptr)?.len(); let n = this.read_c_str(ptr)?.len();
@ -705,7 +707,7 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
} }
"wcslen" => { "wcslen" => {
let [ptr] = let [ptr] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C , link_name, args)?;
let ptr = this.read_pointer(ptr)?; let ptr = this.read_pointer(ptr)?;
// This reads at least 1 byte, so we are already enforcing that this is a valid pointer. // This reads at least 1 byte, so we are already enforcing that this is a valid pointer.
let n = this.read_wchar_t_str(ptr)?.len(); let n = this.read_wchar_t_str(ptr)?.len();
@ -716,7 +718,7 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
} }
"memcpy" => { "memcpy" => {
let [ptr_dest, ptr_src, n] = let [ptr_dest, ptr_src, n] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C , link_name, args)?;
let ptr_dest = this.read_pointer(ptr_dest)?; let ptr_dest = this.read_pointer(ptr_dest)?;
let ptr_src = this.read_pointer(ptr_src)?; let ptr_src = this.read_pointer(ptr_src)?;
let n = this.read_target_usize(n)?; let n = this.read_target_usize(n)?;
@ -731,7 +733,7 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
} }
"strcpy" => { "strcpy" => {
let [ptr_dest, ptr_src] = let [ptr_dest, ptr_src] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C , link_name, args)?;
let ptr_dest = this.read_pointer(ptr_dest)?; let ptr_dest = this.read_pointer(ptr_dest)?;
let ptr_src = this.read_pointer(ptr_src)?; let ptr_src = this.read_pointer(ptr_src)?;
@ -760,7 +762,7 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
| "expm1f" | "expm1f"
| "tgammaf" | "tgammaf"
=> { => {
let [f] = this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; let [f] = this.check_shim(abi, Conv::C , link_name, args)?;
let f = this.read_scalar(f)?.to_f32()?; let f = this.read_scalar(f)?.to_f32()?;
// Using host floats (but it's fine, these operations do not have guaranteed precision). // Using host floats (but it's fine, these operations do not have guaranteed precision).
let f_host = f.to_host(); let f_host = f.to_host();
@ -788,7 +790,7 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
| "atan2f" | "atan2f"
| "fdimf" | "fdimf"
=> { => {
let [f1, f2] = this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; let [f1, f2] = this.check_shim(abi, Conv::C , link_name, args)?;
let f1 = this.read_scalar(f1)?.to_f32()?; let f1 = this.read_scalar(f1)?.to_f32()?;
let f2 = this.read_scalar(f2)?.to_f32()?; let f2 = this.read_scalar(f2)?.to_f32()?;
// underscore case for windows, here and below // underscore case for windows, here and below
@ -817,7 +819,7 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
| "expm1" | "expm1"
| "tgamma" | "tgamma"
=> { => {
let [f] = this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; let [f] = this.check_shim(abi, Conv::C , link_name, args)?;
let f = this.read_scalar(f)?.to_f64()?; let f = this.read_scalar(f)?.to_f64()?;
// Using host floats (but it's fine, these operations do not have guaranteed precision). // Using host floats (but it's fine, these operations do not have guaranteed precision).
let f_host = f.to_host(); let f_host = f.to_host();
@ -845,7 +847,7 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
| "atan2" | "atan2"
| "fdim" | "fdim"
=> { => {
let [f1, f2] = this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; let [f1, f2] = this.check_shim(abi, Conv::C , link_name, args)?;
let f1 = this.read_scalar(f1)?.to_f64()?; let f1 = this.read_scalar(f1)?.to_f64()?;
let f2 = this.read_scalar(f2)?.to_f64()?; let f2 = this.read_scalar(f2)?.to_f64()?;
// underscore case for windows, here and below // underscore case for windows, here and below
@ -866,7 +868,7 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
| "ldexp" | "ldexp"
| "scalbn" | "scalbn"
=> { => {
let [x, exp] = this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; let [x, exp] = this.check_shim(abi, Conv::C , link_name, args)?;
// For radix-2 (binary) systems, `ldexp` and `scalbn` are the same. // For radix-2 (binary) systems, `ldexp` and `scalbn` are the same.
let x = this.read_scalar(x)?.to_f64()?; let x = this.read_scalar(x)?.to_f64()?;
let exp = this.read_scalar(exp)?.to_i32()?; let exp = this.read_scalar(exp)?.to_i32()?;
@ -877,7 +879,7 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
} }
"lgammaf_r" => { "lgammaf_r" => {
let [x, signp] = let [x, signp] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C , link_name, args)?;
let x = this.read_scalar(x)?.to_f32()?; let x = this.read_scalar(x)?.to_f32()?;
let signp = this.deref_pointer(signp)?; let signp = this.deref_pointer(signp)?;
@ -889,7 +891,7 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
} }
"lgamma_r" => { "lgamma_r" => {
let [x, signp] = let [x, signp] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C , link_name, args)?;
let x = this.read_scalar(x)?.to_f64()?; let x = this.read_scalar(x)?.to_f64()?;
let signp = this.deref_pointer(signp)?; let signp = this.deref_pointer(signp)?;
@ -903,7 +905,7 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
// LLVM intrinsics // LLVM intrinsics
"llvm.prefetch" => { "llvm.prefetch" => {
let [p, rw, loc, ty] = let [p, rw, loc, ty] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C , link_name, args)?;
let _ = this.read_pointer(p)?; let _ = this.read_pointer(p)?;
let rw = this.read_scalar(rw)?.to_i32()?; let rw = this.read_scalar(rw)?.to_i32()?;
@ -930,7 +932,7 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
// Used to implement the x86 `_mm{,256,512}_popcnt_epi{8,16,32,64}` and wasm // Used to implement the x86 `_mm{,256,512}_popcnt_epi{8,16,32,64}` and wasm
// `{i,u}8x16_popcnt` functions. // `{i,u}8x16_popcnt` functions.
name if name.starts_with("llvm.ctpop.v") => { name if name.starts_with("llvm.ctpop.v") => {
let [op] = this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; let [op] = this.check_shim(abi, Conv::C , link_name, args)?;
let (op, op_len) = this.project_to_simd(op)?; let (op, op_len) = this.project_to_simd(op)?;
let (dest, dest_len) = this.project_to_simd(dest)?; let (dest, dest_len) = this.project_to_simd(dest)?;
@ -961,7 +963,7 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
} }
// FIXME: Move these to an `arm` submodule. // FIXME: Move these to an `arm` submodule.
"llvm.aarch64.isb" if this.tcx.sess.target.arch == "aarch64" => { "llvm.aarch64.isb" if this.tcx.sess.target.arch == "aarch64" => {
let [arg] = this.check_shim(abi, ExternAbi::Unadjusted, link_name, args)?; let [arg] = this.check_shim(abi, Conv::C, link_name, args)?;
let arg = this.read_scalar(arg)?.to_i32()?; let arg = this.read_scalar(arg)?.to_i32()?;
match arg { match arg {
// SY ("full system scope") // SY ("full system scope")
@ -974,7 +976,7 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
} }
} }
"llvm.arm.hint" if this.tcx.sess.target.arch == "arm" => { "llvm.arm.hint" if this.tcx.sess.target.arch == "arm" => {
let [arg] = this.check_shim(abi, ExternAbi::Unadjusted, link_name, args)?; let [arg] = this.check_shim(abi, Conv::C, link_name, args)?;
let arg = this.read_scalar(arg)?.to_i32()?; let arg = this.read_scalar(arg)?.to_i32()?;
// Note that different arguments might have different target feature requirements. // Note that different arguments might have different target feature requirements.
match arg { match arg {

View file

@ -1,5 +1,8 @@
use rustc_abi::ExternAbi; use rustc_middle::ty::Ty;
use rustc_span::Symbol; use rustc_span::Symbol;
use rustc_target::callconv::{Conv, FnAbi};
use crate::shims::unix::android::thread::prctl; use crate::shims::unix::android::thread::prctl;
use crate::shims::unix::linux_like::epoll::EvalContextExt as _; use crate::shims::unix::linux_like::epoll::EvalContextExt as _;
@ -16,7 +19,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
fn emulate_foreign_item_inner( fn emulate_foreign_item_inner(
&mut self, &mut self,
link_name: Symbol, link_name: Symbol,
abi: ExternAbi, abi: &FnAbi<'tcx, Ty<'tcx>>,
args: &[OpTy<'tcx>], args: &[OpTy<'tcx>],
dest: &MPlaceTy<'tcx>, dest: &MPlaceTy<'tcx>,
) -> InterpResult<'tcx, EmulateItemResult> { ) -> InterpResult<'tcx, EmulateItemResult> {
@ -25,31 +28,31 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
// epoll, eventfd // epoll, eventfd
"epoll_create1" => { "epoll_create1" => {
let [flag] = let [flag] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C, link_name, args)?;
let result = this.epoll_create1(flag)?; let result = this.epoll_create1(flag)?;
this.write_scalar(result, dest)?; this.write_scalar(result, dest)?;
} }
"epoll_ctl" => { "epoll_ctl" => {
let [epfd, op, fd, event] = let [epfd, op, fd, event] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C, link_name, args)?;
let result = this.epoll_ctl(epfd, op, fd, event)?; let result = this.epoll_ctl(epfd, op, fd, event)?;
this.write_scalar(result, dest)?; this.write_scalar(result, dest)?;
} }
"epoll_wait" => { "epoll_wait" => {
let [epfd, events, maxevents, timeout] = let [epfd, events, maxevents, timeout] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C, link_name, args)?;
this.epoll_wait(epfd, events, maxevents, timeout, dest)?; this.epoll_wait(epfd, events, maxevents, timeout, dest)?;
} }
"eventfd" => { "eventfd" => {
let [val, flag] = let [val, flag] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C, link_name, args)?;
let result = this.eventfd(val, flag)?; let result = this.eventfd(val, flag)?;
this.write_scalar(result, dest)?; this.write_scalar(result, dest)?;
} }
// Miscellaneous // Miscellaneous
"__errno" => { "__errno" => {
let [] = this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; let [] = this.check_shim(abi, Conv::C, link_name, args)?;
let errno_place = this.last_error_place()?; let errno_place = this.last_error_place()?;
this.write_scalar(errno_place.to_ref(this).to_scalar(), dest)?; this.write_scalar(errno_place.to_ref(this).to_scalar(), dest)?;
} }

View file

@ -1,5 +1,7 @@
use rustc_abi::{ExternAbi, Size}; use rustc_abi::Size;
use rustc_middle::ty::Ty;
use rustc_span::Symbol; use rustc_span::Symbol;
use rustc_target::callconv::{Conv, FnAbi};
use crate::helpers::check_min_arg_count; use crate::helpers::check_min_arg_count;
use crate::shims::unix::thread::{EvalContextExt as _, ThreadNameResult}; use crate::shims::unix::thread::{EvalContextExt as _, ThreadNameResult};
@ -10,13 +12,13 @@ const TASK_COMM_LEN: usize = 16;
pub fn prctl<'tcx>( pub fn prctl<'tcx>(
ecx: &mut MiriInterpCx<'tcx>, ecx: &mut MiriInterpCx<'tcx>,
link_name: Symbol, link_name: Symbol,
abi: ExternAbi, abi: &FnAbi<'tcx, Ty<'tcx>>,
args: &[OpTy<'tcx>], args: &[OpTy<'tcx>],
dest: &MPlaceTy<'tcx>, dest: &MPlaceTy<'tcx>,
) -> InterpResult<'tcx> { ) -> InterpResult<'tcx> {
// We do not use `check_shim` here because `prctl` is variadic. The argument // We do not use `check_shim` here because `prctl` is variadic. The argument
// count is checked bellow. // count is checked bellow.
ecx.check_abi_and_shim_symbol_clash(abi, ExternAbi::C { unwind: false }, link_name)?; ecx.check_abi_and_shim_symbol_clash(abi, Conv::C, link_name)?;
// FIXME: Use constants once https://github.com/rust-lang/libc/pull/3941 backported to the 0.2 branch. // FIXME: Use constants once https://github.com/rust-lang/libc/pull/3941 backported to the 0.2 branch.
let pr_set_name = 15; let pr_set_name = 15;

View file

@ -1,9 +1,11 @@
use std::ffi::OsStr; use std::ffi::OsStr;
use std::str; use std::str;
use rustc_abi::{ExternAbi, Size}; use rustc_abi::Size;
use rustc_middle::ty::layout::LayoutOf; use rustc_middle::ty::layout::LayoutOf;
use rustc_middle::ty::Ty;
use rustc_span::Symbol; use rustc_span::Symbol;
use rustc_target::callconv::{Conv, FnAbi};
use self::shims::unix::android::foreign_items as android; use self::shims::unix::android::foreign_items as android;
use self::shims::unix::freebsd::foreign_items as freebsd; use self::shims::unix::freebsd::foreign_items as freebsd;
@ -100,7 +102,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
fn emulate_foreign_item_inner( fn emulate_foreign_item_inner(
&mut self, &mut self,
link_name: Symbol, link_name: Symbol,
abi: ExternAbi, abi: &FnAbi<'tcx, Ty<'tcx>>,
args: &[OpTy<'tcx>], args: &[OpTy<'tcx>],
dest: &MPlaceTy<'tcx>, dest: &MPlaceTy<'tcx>,
) -> InterpResult<'tcx, EmulateItemResult> { ) -> InterpResult<'tcx, EmulateItemResult> {
@ -111,54 +113,52 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
match link_name.as_str() { match link_name.as_str() {
// Environment related shims // Environment related shims
"getenv" => { "getenv" => {
let [name] = this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; let [name] = this.check_shim(abi, Conv::C , link_name, args)?;
let result = this.getenv(name)?; let result = this.getenv(name)?;
this.write_pointer(result, dest)?; this.write_pointer(result, dest)?;
} }
"unsetenv" => { "unsetenv" => {
let [name] = this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; let [name] = this.check_shim(abi, Conv::C , link_name, args)?;
let result = this.unsetenv(name)?; let result = this.unsetenv(name)?;
this.write_scalar(result, dest)?; this.write_scalar(result, dest)?;
} }
"setenv" => { "setenv" => {
let [name, value, overwrite] = this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; let [name, value, overwrite] = this.check_shim(abi, Conv::C , link_name, args)?;
this.read_scalar(overwrite)?.to_i32()?; this.read_scalar(overwrite)?.to_i32()?;
let result = this.setenv(name, value)?; let result = this.setenv(name, value)?;
this.write_scalar(result, dest)?; this.write_scalar(result, dest)?;
} }
"getcwd" => { "getcwd" => {
let [buf, size] = this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; let [buf, size] = this.check_shim(abi, Conv::C , link_name, args)?;
let result = this.getcwd(buf, size)?; let result = this.getcwd(buf, size)?;
this.write_pointer(result, dest)?; this.write_pointer(result, dest)?;
} }
"chdir" => { "chdir" => {
let [path] = this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; let [path] = this.check_shim(abi, Conv::C , link_name, args)?;
let result = this.chdir(path)?; let result = this.chdir(path)?;
this.write_scalar(result, dest)?; this.write_scalar(result, dest)?;
} }
"getpid" => { "getpid" => {
let [] = this.check_shim(abi, ExternAbi::C { unwind: false}, link_name, args)?; let [] = this.check_shim(abi, Conv::C , link_name, args)?;
let result = this.getpid()?; let result = this.getpid()?;
this.write_scalar(result, dest)?; this.write_scalar(result, dest)?;
} }
"sysconf" => { "sysconf" => {
let [val] = let [val] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C, link_name, args)?;
let result = this.sysconf(val)?; let result = this.sysconf(val)?;
this.write_scalar(result, dest)?; this.write_scalar(result, dest)?;
} }
// File descriptors // File descriptors
"read" => { "read" => {
let [fd, buf, count] = this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; let [fd, buf, count] = this.check_shim(abi, Conv::C , link_name, args)?;
let fd = this.read_scalar(fd)?.to_i32()?; let fd = this.read_scalar(fd)?.to_i32()?;
let buf = this.read_pointer(buf)?; let buf = this.read_pointer(buf)?;
let count = this.read_target_usize(count)?; let count = this.read_target_usize(count)?;
this.read(fd, buf, count, None, dest)?; this.read(fd, buf, count, None, dest)?;
} }
"write" => { "write" => {
let [fd, buf, n] = this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; let [fd, buf, n] = this.check_shim(abi, Conv::C , link_name, args)?;
let fd = this.read_scalar(fd)?.to_i32()?; let fd = this.read_scalar(fd)?.to_i32()?;
let buf = this.read_pointer(buf)?; let buf = this.read_pointer(buf)?;
let count = this.read_target_usize(n)?; let count = this.read_target_usize(n)?;
@ -166,7 +166,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
this.write(fd, buf, count, None, dest)?; this.write(fd, buf, count, None, dest)?;
} }
"pread" => { "pread" => {
let [fd, buf, count, offset] = this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; let [fd, buf, count, offset] = this.check_shim(abi, Conv::C , link_name, args)?;
let fd = this.read_scalar(fd)?.to_i32()?; let fd = this.read_scalar(fd)?.to_i32()?;
let buf = this.read_pointer(buf)?; let buf = this.read_pointer(buf)?;
let count = this.read_target_usize(count)?; let count = this.read_target_usize(count)?;
@ -174,7 +174,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
this.read(fd, buf, count, Some(offset), dest)?; this.read(fd, buf, count, Some(offset), dest)?;
} }
"pwrite" => { "pwrite" => {
let [fd, buf, n, offset] = this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; let [fd, buf, n, offset] = this.check_shim(abi, Conv::C , link_name, args)?;
let fd = this.read_scalar(fd)?.to_i32()?; let fd = this.read_scalar(fd)?.to_i32()?;
let buf = this.read_pointer(buf)?; let buf = this.read_pointer(buf)?;
let count = this.read_target_usize(n)?; let count = this.read_target_usize(n)?;
@ -183,7 +183,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
this.write(fd, buf, count, Some(offset), dest)?; this.write(fd, buf, count, Some(offset), dest)?;
} }
"pread64" => { "pread64" => {
let [fd, buf, count, offset] = this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; let [fd, buf, count, offset] = this.check_shim(abi, Conv::C , link_name, args)?;
let fd = this.read_scalar(fd)?.to_i32()?; let fd = this.read_scalar(fd)?.to_i32()?;
let buf = this.read_pointer(buf)?; let buf = this.read_pointer(buf)?;
let count = this.read_target_usize(count)?; let count = this.read_target_usize(count)?;
@ -191,7 +191,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
this.read(fd, buf, count, Some(offset), dest)?; this.read(fd, buf, count, Some(offset), dest)?;
} }
"pwrite64" => { "pwrite64" => {
let [fd, buf, n, offset] = this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; let [fd, buf, n, offset] = this.check_shim(abi, Conv::C , link_name, args)?;
let fd = this.read_scalar(fd)?.to_i32()?; let fd = this.read_scalar(fd)?.to_i32()?;
let buf = this.read_pointer(buf)?; let buf = this.read_pointer(buf)?;
let count = this.read_target_usize(n)?; let count = this.read_target_usize(n)?;
@ -200,32 +200,32 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
this.write(fd, buf, count, Some(offset), dest)?; this.write(fd, buf, count, Some(offset), dest)?;
} }
"close" => { "close" => {
let [fd] = this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; let [fd] = this.check_shim(abi, Conv::C , link_name, args)?;
let result = this.close(fd)?; let result = this.close(fd)?;
this.write_scalar(result, dest)?; this.write_scalar(result, dest)?;
} }
"fcntl" => { "fcntl" => {
// `fcntl` is variadic. The argument count is checked based on the first argument // `fcntl` is variadic. The argument count is checked based on the first argument
// in `this.fcntl()`, so we do not use `check_shim` here. // in `this.fcntl()`, so we do not use `check_shim` here.
this.check_abi_and_shim_symbol_clash(abi, ExternAbi::C { unwind: false }, link_name)?; this.check_abi_and_shim_symbol_clash(abi, Conv::C , link_name)?;
let result = this.fcntl(args)?; let result = this.fcntl(args)?;
this.write_scalar(result, dest)?; this.write_scalar(result, dest)?;
} }
"dup" => { "dup" => {
let [old_fd] = this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; let [old_fd] = this.check_shim(abi, Conv::C , link_name, args)?;
let old_fd = this.read_scalar(old_fd)?.to_i32()?; let old_fd = this.read_scalar(old_fd)?.to_i32()?;
let new_fd = this.dup(old_fd)?; let new_fd = this.dup(old_fd)?;
this.write_scalar(new_fd, dest)?; this.write_scalar(new_fd, dest)?;
} }
"dup2" => { "dup2" => {
let [old_fd, new_fd] = this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; let [old_fd, new_fd] = this.check_shim(abi, Conv::C , link_name, args)?;
let old_fd = this.read_scalar(old_fd)?.to_i32()?; let old_fd = this.read_scalar(old_fd)?.to_i32()?;
let new_fd = this.read_scalar(new_fd)?.to_i32()?; let new_fd = this.read_scalar(new_fd)?.to_i32()?;
let result = this.dup2(old_fd, new_fd)?; let result = this.dup2(old_fd, new_fd)?;
this.write_scalar(result, dest)?; this.write_scalar(result, dest)?;
} }
"flock" => { "flock" => {
let [fd, op] = this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; let [fd, op] = this.check_shim(abi, Conv::C , link_name, args)?;
let fd = this.read_scalar(fd)?.to_i32()?; let fd = this.read_scalar(fd)?.to_i32()?;
let op = this.read_scalar(op)?.to_i32()?; let op = this.read_scalar(op)?.to_i32()?;
let result = this.flock(fd, op)?; let result = this.flock(fd, op)?;
@ -235,47 +235,47 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
// File and file system access // File and file system access
"open" | "open64" => { "open" | "open64" => {
// `open` is variadic, the third argument is only present when the second argument has O_CREAT (or on linux O_TMPFILE, but miri doesn't support that) set // `open` is variadic, the third argument is only present when the second argument has O_CREAT (or on linux O_TMPFILE, but miri doesn't support that) set
this.check_abi_and_shim_symbol_clash(abi, ExternAbi::C { unwind: false }, link_name)?; this.check_abi_and_shim_symbol_clash(abi, Conv::C , link_name)?;
let result = this.open(args)?; let result = this.open(args)?;
this.write_scalar(result, dest)?; this.write_scalar(result, dest)?;
} }
"unlink" => { "unlink" => {
let [path] = this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; let [path] = this.check_shim(abi, Conv::C , link_name, args)?;
let result = this.unlink(path)?; let result = this.unlink(path)?;
this.write_scalar(result, dest)?; this.write_scalar(result, dest)?;
} }
"symlink" => { "symlink" => {
let [target, linkpath] = this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; let [target, linkpath] = this.check_shim(abi, Conv::C , link_name, args)?;
let result = this.symlink(target, linkpath)?; let result = this.symlink(target, linkpath)?;
this.write_scalar(result, dest)?; this.write_scalar(result, dest)?;
} }
"rename" => { "rename" => {
let [oldpath, newpath] = this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; let [oldpath, newpath] = this.check_shim(abi, Conv::C , link_name, args)?;
let result = this.rename(oldpath, newpath)?; let result = this.rename(oldpath, newpath)?;
this.write_scalar(result, dest)?; this.write_scalar(result, dest)?;
} }
"mkdir" => { "mkdir" => {
let [path, mode] = this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; let [path, mode] = this.check_shim(abi, Conv::C , link_name, args)?;
let result = this.mkdir(path, mode)?; let result = this.mkdir(path, mode)?;
this.write_scalar(result, dest)?; this.write_scalar(result, dest)?;
} }
"rmdir" => { "rmdir" => {
let [path] = this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; let [path] = this.check_shim(abi, Conv::C , link_name, args)?;
let result = this.rmdir(path)?; let result = this.rmdir(path)?;
this.write_scalar(result, dest)?; this.write_scalar(result, dest)?;
} }
"opendir" => { "opendir" => {
let [name] = this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; let [name] = this.check_shim(abi, Conv::C , link_name, args)?;
let result = this.opendir(name)?; let result = this.opendir(name)?;
this.write_scalar(result, dest)?; this.write_scalar(result, dest)?;
} }
"closedir" => { "closedir" => {
let [dirp] = this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; let [dirp] = this.check_shim(abi, Conv::C , link_name, args)?;
let result = this.closedir(dirp)?; let result = this.closedir(dirp)?;
this.write_scalar(result, dest)?; this.write_scalar(result, dest)?;
} }
"lseek64" => { "lseek64" => {
let [fd, offset, whence] = this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; let [fd, offset, whence] = this.check_shim(abi, Conv::C , link_name, args)?;
let fd = this.read_scalar(fd)?.to_i32()?; let fd = this.read_scalar(fd)?.to_i32()?;
let offset = this.read_scalar(offset)?.to_i64()?; let offset = this.read_scalar(offset)?.to_i64()?;
let whence = this.read_scalar(whence)?.to_i32()?; let whence = this.read_scalar(whence)?.to_i32()?;
@ -283,7 +283,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
this.write_scalar(result, dest)?; this.write_scalar(result, dest)?;
} }
"lseek" => { "lseek" => {
let [fd, offset, whence] = this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; let [fd, offset, whence] = this.check_shim(abi, Conv::C , link_name, args)?;
let fd = this.read_scalar(fd)?.to_i32()?; let fd = this.read_scalar(fd)?.to_i32()?;
let offset = this.read_scalar(offset)?.to_int(this.libc_ty_layout("off_t").size)?; let offset = this.read_scalar(offset)?.to_int(this.libc_ty_layout("off_t").size)?;
let whence = this.read_scalar(whence)?.to_i32()?; let whence = this.read_scalar(whence)?.to_i32()?;
@ -292,7 +292,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
} }
"ftruncate64" => { "ftruncate64" => {
let [fd, length] = let [fd, length] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C , link_name, args)?;
let fd = this.read_scalar(fd)?.to_i32()?; let fd = this.read_scalar(fd)?.to_i32()?;
let length = this.read_scalar(length)?.to_i64()?; let length = this.read_scalar(length)?.to_i64()?;
let result = this.ftruncate64(fd, length.into())?; let result = this.ftruncate64(fd, length.into())?;
@ -300,30 +300,30 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
} }
"ftruncate" => { "ftruncate" => {
let [fd, length] = let [fd, length] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C , link_name, args)?;
let fd = this.read_scalar(fd)?.to_i32()?; let fd = this.read_scalar(fd)?.to_i32()?;
let length = this.read_scalar(length)?.to_int(this.libc_ty_layout("off_t").size)?; let length = this.read_scalar(length)?.to_int(this.libc_ty_layout("off_t").size)?;
let result = this.ftruncate64(fd, length)?; let result = this.ftruncate64(fd, length)?;
this.write_scalar(result, dest)?; this.write_scalar(result, dest)?;
} }
"fsync" => { "fsync" => {
let [fd] = this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; let [fd] = this.check_shim(abi, Conv::C , link_name, args)?;
let result = this.fsync(fd)?; let result = this.fsync(fd)?;
this.write_scalar(result, dest)?; this.write_scalar(result, dest)?;
} }
"fdatasync" => { "fdatasync" => {
let [fd] = this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; let [fd] = this.check_shim(abi, Conv::C , link_name, args)?;
let result = this.fdatasync(fd)?; let result = this.fdatasync(fd)?;
this.write_scalar(result, dest)?; this.write_scalar(result, dest)?;
} }
"readlink" => { "readlink" => {
let [pathname, buf, bufsize] = this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; let [pathname, buf, bufsize] = this.check_shim(abi, Conv::C , link_name, args)?;
let result = this.readlink(pathname, buf, bufsize)?; let result = this.readlink(pathname, buf, bufsize)?;
this.write_scalar(Scalar::from_target_isize(result, this), dest)?; this.write_scalar(Scalar::from_target_isize(result, this), dest)?;
} }
"posix_fadvise" => { "posix_fadvise" => {
let [fd, offset, len, advice] = let [fd, offset, len, advice] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C , link_name, args)?;
this.read_scalar(fd)?.to_i32()?; this.read_scalar(fd)?.to_i32()?;
this.read_target_isize(offset)?; this.read_target_isize(offset)?;
this.read_target_isize(len)?; this.read_target_isize(len)?;
@ -332,12 +332,12 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
this.write_null(dest)?; this.write_null(dest)?;
} }
"realpath" => { "realpath" => {
let [path, resolved_path] = this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; let [path, resolved_path] = this.check_shim(abi, Conv::C , link_name, args)?;
let result = this.realpath(path, resolved_path)?; let result = this.realpath(path, resolved_path)?;
this.write_scalar(result, dest)?; this.write_scalar(result, dest)?;
} }
"mkstemp" => { "mkstemp" => {
let [template] = this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; let [template] = this.check_shim(abi, Conv::C , link_name, args)?;
let result = this.mkstemp(template)?; let result = this.mkstemp(template)?;
this.write_scalar(result, dest)?; this.write_scalar(result, dest)?;
} }
@ -345,13 +345,13 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
// Unnamed sockets and pipes // Unnamed sockets and pipes
"socketpair" => { "socketpair" => {
let [domain, type_, protocol, sv] = let [domain, type_, protocol, sv] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C , link_name, args)?;
let result = this.socketpair(domain, type_, protocol, sv)?; let result = this.socketpair(domain, type_, protocol, sv)?;
this.write_scalar(result, dest)?; this.write_scalar(result, dest)?;
} }
"pipe" => { "pipe" => {
let [pipefd] = let [pipefd] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C , link_name, args)?;
let result = this.pipe2(pipefd, /*flags*/ None)?; let result = this.pipe2(pipefd, /*flags*/ None)?;
this.write_scalar(result, dest)?; this.write_scalar(result, dest)?;
} }
@ -364,44 +364,44 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
); );
} }
let [pipefd, flags] = let [pipefd, flags] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C , link_name, args)?;
let result = this.pipe2(pipefd, Some(flags))?; let result = this.pipe2(pipefd, Some(flags))?;
this.write_scalar(result, dest)?; this.write_scalar(result, dest)?;
} }
// Time // Time
"gettimeofday" => { "gettimeofday" => {
let [tv, tz] = this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; let [tv, tz] = this.check_shim(abi, Conv::C , link_name, args)?;
let result = this.gettimeofday(tv, tz)?; let result = this.gettimeofday(tv, tz)?;
this.write_scalar(result, dest)?; this.write_scalar(result, dest)?;
} }
"localtime_r" => { "localtime_r" => {
let [timep, result_op] = this.check_shim(abi, ExternAbi::C {unwind: false}, link_name, args)?; let [timep, result_op] = this.check_shim(abi, Conv::C , link_name, args)?;
let result = this.localtime_r(timep, result_op)?; let result = this.localtime_r(timep, result_op)?;
this.write_pointer(result, dest)?; this.write_pointer(result, dest)?;
} }
"clock_gettime" => { "clock_gettime" => {
let [clk_id, tp] = let [clk_id, tp] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C , link_name, args)?;
let result = this.clock_gettime(clk_id, tp)?; let result = this.clock_gettime(clk_id, tp)?;
this.write_scalar(result, dest)?; this.write_scalar(result, dest)?;
} }
// Allocation // Allocation
"posix_memalign" => { "posix_memalign" => {
let [memptr, align, size] = this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; let [memptr, align, size] = this.check_shim(abi, Conv::C , link_name, args)?;
let result = this.posix_memalign(memptr, align, size)?; let result = this.posix_memalign(memptr, align, size)?;
this.write_scalar(result, dest)?; this.write_scalar(result, dest)?;
} }
"mmap" => { "mmap" => {
let [addr, length, prot, flags, fd, offset] = this.check_shim(abi, ExternAbi::C {unwind: false}, link_name, args)?; let [addr, length, prot, flags, fd, offset] = this.check_shim(abi, Conv::C , link_name, args)?;
let offset = this.read_scalar(offset)?.to_int(this.libc_ty_layout("off_t").size)?; let offset = this.read_scalar(offset)?.to_int(this.libc_ty_layout("off_t").size)?;
let ptr = this.mmap(addr, length, prot, flags, fd, offset)?; let ptr = this.mmap(addr, length, prot, flags, fd, offset)?;
this.write_scalar(ptr, dest)?; this.write_scalar(ptr, dest)?;
} }
"munmap" => { "munmap" => {
let [addr, length] = this.check_shim(abi, ExternAbi::C {unwind: false}, link_name, args)?; let [addr, length] = this.check_shim(abi, Conv::C , link_name, args)?;
let result = this.munmap(addr, length)?; let result = this.munmap(addr, length)?;
this.write_scalar(result, dest)?; this.write_scalar(result, dest)?;
} }
@ -415,7 +415,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
); );
} }
let [ptr, nmemb, size] = let [ptr, nmemb, size] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C , link_name, args)?;
let ptr = this.read_pointer(ptr)?; let ptr = this.read_pointer(ptr)?;
let nmemb = this.read_target_usize(nmemb)?; let nmemb = this.read_target_usize(nmemb)?;
let size = this.read_target_usize(size)?; let size = this.read_target_usize(size)?;
@ -439,14 +439,14 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
// This is a C11 function, we assume all Unixes have it. // This is a C11 function, we assume all Unixes have it.
// (MSVC explicitly does not support this.) // (MSVC explicitly does not support this.)
let [align, size] = let [align, size] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C , link_name, args)?;
let res = this.aligned_alloc(align, size)?; let res = this.aligned_alloc(align, size)?;
this.write_pointer(res, dest)?; this.write_pointer(res, dest)?;
} }
// Dynamic symbol loading // Dynamic symbol loading
"dlsym" => { "dlsym" => {
let [handle, symbol] = this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; let [handle, symbol] = this.check_shim(abi, Conv::C , link_name, args)?;
this.read_target_usize(handle)?; this.read_target_usize(handle)?;
let symbol = this.read_pointer(symbol)?; let symbol = this.read_pointer(symbol)?;
let name = this.read_c_str(symbol)?; let name = this.read_c_str(symbol)?;
@ -460,7 +460,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
// Thread-local storage // Thread-local storage
"pthread_key_create" => { "pthread_key_create" => {
let [key, dtor] = this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; let [key, dtor] = this.check_shim(abi, Conv::C , link_name, args)?;
let key_place = this.deref_pointer_as(key, this.libc_ty_layout("pthread_key_t"))?; let key_place = this.deref_pointer_as(key, this.libc_ty_layout("pthread_key_t"))?;
let dtor = this.read_pointer(dtor)?; let dtor = this.read_pointer(dtor)?;
@ -488,21 +488,21 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
this.write_null(dest)?; this.write_null(dest)?;
} }
"pthread_key_delete" => { "pthread_key_delete" => {
let [key] = this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; let [key] = this.check_shim(abi, Conv::C , link_name, args)?;
let key = this.read_scalar(key)?.to_bits(key.layout.size)?; let key = this.read_scalar(key)?.to_bits(key.layout.size)?;
this.machine.tls.delete_tls_key(key)?; this.machine.tls.delete_tls_key(key)?;
// Return success (0) // Return success (0)
this.write_null(dest)?; this.write_null(dest)?;
} }
"pthread_getspecific" => { "pthread_getspecific" => {
let [key] = this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; let [key] = this.check_shim(abi, Conv::C , link_name, args)?;
let key = this.read_scalar(key)?.to_bits(key.layout.size)?; let key = this.read_scalar(key)?.to_bits(key.layout.size)?;
let active_thread = this.active_thread(); let active_thread = this.active_thread();
let ptr = this.machine.tls.load_tls(key, active_thread, this)?; let ptr = this.machine.tls.load_tls(key, active_thread, this)?;
this.write_scalar(ptr, dest)?; this.write_scalar(ptr, dest)?;
} }
"pthread_setspecific" => { "pthread_setspecific" => {
let [key, new_ptr] = this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; let [key, new_ptr] = this.check_shim(abi, Conv::C , link_name, args)?;
let key = this.read_scalar(key)?.to_bits(key.layout.size)?; let key = this.read_scalar(key)?.to_bits(key.layout.size)?;
let active_thread = this.active_thread(); let active_thread = this.active_thread();
let new_data = this.read_scalar(new_ptr)?; let new_data = this.read_scalar(new_ptr)?;
@ -514,151 +514,151 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
// Synchronization primitives // Synchronization primitives
"pthread_mutexattr_init" => { "pthread_mutexattr_init" => {
let [attr] = this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; let [attr] = this.check_shim(abi, Conv::C , link_name, args)?;
this.pthread_mutexattr_init(attr)?; this.pthread_mutexattr_init(attr)?;
this.write_null(dest)?; this.write_null(dest)?;
} }
"pthread_mutexattr_settype" => { "pthread_mutexattr_settype" => {
let [attr, kind] = this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; let [attr, kind] = this.check_shim(abi, Conv::C , link_name, args)?;
let result = this.pthread_mutexattr_settype(attr, kind)?; let result = this.pthread_mutexattr_settype(attr, kind)?;
this.write_scalar(result, dest)?; this.write_scalar(result, dest)?;
} }
"pthread_mutexattr_destroy" => { "pthread_mutexattr_destroy" => {
let [attr] = this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; let [attr] = this.check_shim(abi, Conv::C , link_name, args)?;
this.pthread_mutexattr_destroy(attr)?; this.pthread_mutexattr_destroy(attr)?;
this.write_null(dest)?; this.write_null(dest)?;
} }
"pthread_mutex_init" => { "pthread_mutex_init" => {
let [mutex, attr] = this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; let [mutex, attr] = this.check_shim(abi, Conv::C , link_name, args)?;
this.pthread_mutex_init(mutex, attr)?; this.pthread_mutex_init(mutex, attr)?;
this.write_null(dest)?; this.write_null(dest)?;
} }
"pthread_mutex_lock" => { "pthread_mutex_lock" => {
let [mutex] = this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; let [mutex] = this.check_shim(abi, Conv::C , link_name, args)?;
this.pthread_mutex_lock(mutex, dest)?; this.pthread_mutex_lock(mutex, dest)?;
} }
"pthread_mutex_trylock" => { "pthread_mutex_trylock" => {
let [mutex] = this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; let [mutex] = this.check_shim(abi, Conv::C , link_name, args)?;
let result = this.pthread_mutex_trylock(mutex)?; let result = this.pthread_mutex_trylock(mutex)?;
this.write_scalar(result, dest)?; this.write_scalar(result, dest)?;
} }
"pthread_mutex_unlock" => { "pthread_mutex_unlock" => {
let [mutex] = this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; let [mutex] = this.check_shim(abi, Conv::C , link_name, args)?;
let result = this.pthread_mutex_unlock(mutex)?; let result = this.pthread_mutex_unlock(mutex)?;
this.write_scalar(result, dest)?; this.write_scalar(result, dest)?;
} }
"pthread_mutex_destroy" => { "pthread_mutex_destroy" => {
let [mutex] = this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; let [mutex] = this.check_shim(abi, Conv::C , link_name, args)?;
this.pthread_mutex_destroy(mutex)?; this.pthread_mutex_destroy(mutex)?;
this.write_int(0, dest)?; this.write_int(0, dest)?;
} }
"pthread_rwlock_rdlock" => { "pthread_rwlock_rdlock" => {
let [rwlock] = this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; let [rwlock] = this.check_shim(abi, Conv::C , link_name, args)?;
this.pthread_rwlock_rdlock(rwlock, dest)?; this.pthread_rwlock_rdlock(rwlock, dest)?;
} }
"pthread_rwlock_tryrdlock" => { "pthread_rwlock_tryrdlock" => {
let [rwlock] = this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; let [rwlock] = this.check_shim(abi, Conv::C , link_name, args)?;
let result = this.pthread_rwlock_tryrdlock(rwlock)?; let result = this.pthread_rwlock_tryrdlock(rwlock)?;
this.write_scalar(result, dest)?; this.write_scalar(result, dest)?;
} }
"pthread_rwlock_wrlock" => { "pthread_rwlock_wrlock" => {
let [rwlock] = this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; let [rwlock] = this.check_shim(abi, Conv::C , link_name, args)?;
this.pthread_rwlock_wrlock(rwlock, dest)?; this.pthread_rwlock_wrlock(rwlock, dest)?;
} }
"pthread_rwlock_trywrlock" => { "pthread_rwlock_trywrlock" => {
let [rwlock] = this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; let [rwlock] = this.check_shim(abi, Conv::C , link_name, args)?;
let result = this.pthread_rwlock_trywrlock(rwlock)?; let result = this.pthread_rwlock_trywrlock(rwlock)?;
this.write_scalar(result, dest)?; this.write_scalar(result, dest)?;
} }
"pthread_rwlock_unlock" => { "pthread_rwlock_unlock" => {
let [rwlock] = this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; let [rwlock] = this.check_shim(abi, Conv::C , link_name, args)?;
this.pthread_rwlock_unlock(rwlock)?; this.pthread_rwlock_unlock(rwlock)?;
this.write_null(dest)?; this.write_null(dest)?;
} }
"pthread_rwlock_destroy" => { "pthread_rwlock_destroy" => {
let [rwlock] = this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; let [rwlock] = this.check_shim(abi, Conv::C , link_name, args)?;
this.pthread_rwlock_destroy(rwlock)?; this.pthread_rwlock_destroy(rwlock)?;
this.write_null(dest)?; this.write_null(dest)?;
} }
"pthread_condattr_init" => { "pthread_condattr_init" => {
let [attr] = this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; let [attr] = this.check_shim(abi, Conv::C , link_name, args)?;
this.pthread_condattr_init(attr)?; this.pthread_condattr_init(attr)?;
this.write_null(dest)?; this.write_null(dest)?;
} }
"pthread_condattr_setclock" => { "pthread_condattr_setclock" => {
let [attr, clock_id] = let [attr, clock_id] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C , link_name, args)?;
let result = this.pthread_condattr_setclock(attr, clock_id)?; let result = this.pthread_condattr_setclock(attr, clock_id)?;
this.write_scalar(result, dest)?; this.write_scalar(result, dest)?;
} }
"pthread_condattr_getclock" => { "pthread_condattr_getclock" => {
let [attr, clock_id] = let [attr, clock_id] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C , link_name, args)?;
this.pthread_condattr_getclock(attr, clock_id)?; this.pthread_condattr_getclock(attr, clock_id)?;
this.write_null(dest)?; this.write_null(dest)?;
} }
"pthread_condattr_destroy" => { "pthread_condattr_destroy" => {
let [attr] = this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; let [attr] = this.check_shim(abi, Conv::C , link_name, args)?;
this.pthread_condattr_destroy(attr)?; this.pthread_condattr_destroy(attr)?;
this.write_null(dest)?; this.write_null(dest)?;
} }
"pthread_cond_init" => { "pthread_cond_init" => {
let [cond, attr] = this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; let [cond, attr] = this.check_shim(abi, Conv::C , link_name, args)?;
this.pthread_cond_init(cond, attr)?; this.pthread_cond_init(cond, attr)?;
this.write_null(dest)?; this.write_null(dest)?;
} }
"pthread_cond_signal" => { "pthread_cond_signal" => {
let [cond] = this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; let [cond] = this.check_shim(abi, Conv::C , link_name, args)?;
this.pthread_cond_signal(cond)?; this.pthread_cond_signal(cond)?;
this.write_null(dest)?; this.write_null(dest)?;
} }
"pthread_cond_broadcast" => { "pthread_cond_broadcast" => {
let [cond] = this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; let [cond] = this.check_shim(abi, Conv::C , link_name, args)?;
this.pthread_cond_broadcast(cond)?; this.pthread_cond_broadcast(cond)?;
this.write_null(dest)?; this.write_null(dest)?;
} }
"pthread_cond_wait" => { "pthread_cond_wait" => {
let [cond, mutex] = this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; let [cond, mutex] = this.check_shim(abi, Conv::C , link_name, args)?;
this.pthread_cond_wait(cond, mutex, dest)?; this.pthread_cond_wait(cond, mutex, dest)?;
} }
"pthread_cond_timedwait" => { "pthread_cond_timedwait" => {
let [cond, mutex, abstime] = this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; let [cond, mutex, abstime] = this.check_shim(abi, Conv::C , link_name, args)?;
this.pthread_cond_timedwait(cond, mutex, abstime, dest)?; this.pthread_cond_timedwait(cond, mutex, abstime, dest)?;
} }
"pthread_cond_destroy" => { "pthread_cond_destroy" => {
let [cond] = this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; let [cond] = this.check_shim(abi, Conv::C , link_name, args)?;
this.pthread_cond_destroy(cond)?; this.pthread_cond_destroy(cond)?;
this.write_null(dest)?; this.write_null(dest)?;
} }
// Threading // Threading
"pthread_create" => { "pthread_create" => {
let [thread, attr, start, arg] = this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; let [thread, attr, start, arg] = this.check_shim(abi, Conv::C , link_name, args)?;
this.pthread_create(thread, attr, start, arg)?; this.pthread_create(thread, attr, start, arg)?;
this.write_null(dest)?; this.write_null(dest)?;
} }
"pthread_join" => { "pthread_join" => {
let [thread, retval] = this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; let [thread, retval] = this.check_shim(abi, Conv::C , link_name, args)?;
let res = this.pthread_join(thread, retval)?; let res = this.pthread_join(thread, retval)?;
this.write_scalar(res, dest)?; this.write_scalar(res, dest)?;
} }
"pthread_detach" => { "pthread_detach" => {
let [thread] = this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; let [thread] = this.check_shim(abi, Conv::C , link_name, args)?;
let res = this.pthread_detach(thread)?; let res = this.pthread_detach(thread)?;
this.write_scalar(res, dest)?; this.write_scalar(res, dest)?;
} }
"pthread_self" => { "pthread_self" => {
let [] = this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; let [] = this.check_shim(abi, Conv::C , link_name, args)?;
let res = this.pthread_self()?; let res = this.pthread_self()?;
this.write_scalar(res, dest)?; this.write_scalar(res, dest)?;
} }
"sched_yield" => { "sched_yield" => {
let [] = this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; let [] = this.check_shim(abi, Conv::C , link_name, args)?;
this.sched_yield()?; this.sched_yield()?;
this.write_null(dest)?; this.write_null(dest)?;
} }
"nanosleep" => { "nanosleep" => {
let [req, rem] = this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; let [req, rem] = this.check_shim(abi, Conv::C , link_name, args)?;
let result = this.nanosleep(req, rem)?; let result = this.nanosleep(req, rem)?;
this.write_scalar(result, dest)?; this.write_scalar(result, dest)?;
} }
@ -672,7 +672,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
} }
let [pid, cpusetsize, mask] = let [pid, cpusetsize, mask] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C , link_name, args)?;
let pid = this.read_scalar(pid)?.to_u32()?; let pid = this.read_scalar(pid)?.to_u32()?;
let cpusetsize = this.read_target_usize(cpusetsize)?; let cpusetsize = this.read_target_usize(cpusetsize)?;
let mask = this.read_pointer(mask)?; let mask = this.read_pointer(mask)?;
@ -712,7 +712,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
} }
let [pid, cpusetsize, mask] = let [pid, cpusetsize, mask] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C , link_name, args)?;
let pid = this.read_scalar(pid)?.to_u32()?; let pid = this.read_scalar(pid)?.to_u32()?;
let cpusetsize = this.read_target_usize(cpusetsize)?; let cpusetsize = this.read_target_usize(cpusetsize)?;
let mask = this.read_pointer(mask)?; let mask = this.read_pointer(mask)?;
@ -748,12 +748,12 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
// Miscellaneous // Miscellaneous
"isatty" => { "isatty" => {
let [fd] = this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; let [fd] = this.check_shim(abi, Conv::C , link_name, args)?;
let result = this.isatty(fd)?; let result = this.isatty(fd)?;
this.write_scalar(result, dest)?; this.write_scalar(result, dest)?;
} }
"pthread_atfork" => { "pthread_atfork" => {
let [prepare, parent, child] = this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; let [prepare, parent, child] = this.check_shim(abi, Conv::C , link_name, args)?;
this.read_pointer(prepare)?; this.read_pointer(prepare)?;
this.read_pointer(parent)?; this.read_pointer(parent)?;
this.read_pointer(child)?; this.read_pointer(child)?;
@ -771,7 +771,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
} }
let [buf, bufsize] = let [buf, bufsize] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C , link_name, args)?;
let buf = this.read_pointer(buf)?; let buf = this.read_pointer(buf)?;
let bufsize = this.read_target_usize(bufsize)?; let bufsize = this.read_target_usize(bufsize)?;
@ -790,7 +790,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
"strerror_r" => { "strerror_r" => {
let [errnum, buf, buflen] = let [errnum, buf, buflen] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C, link_name, args)?;
let result = this.strerror_r(errnum, buf, buflen)?; let result = this.strerror_r(errnum, buf, buflen)?;
this.write_scalar(result, dest)?; this.write_scalar(result, dest)?;
} }
@ -805,7 +805,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
); );
} }
let [ptr, len, flags] = let [ptr, len, flags] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C , link_name, args)?;
let ptr = this.read_pointer(ptr)?; let ptr = this.read_pointer(ptr)?;
let len = this.read_target_usize(len)?; let len = this.read_target_usize(len)?;
let _flags = this.read_scalar(flags)?.to_i32()?; let _flags = this.read_scalar(flags)?.to_i32()?;
@ -822,7 +822,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
this.tcx.sess.target.os this.tcx.sess.target.os
); );
} }
let [ptr, len] = this.check_shim(abi, ExternAbi::C { unwind: false}, link_name, args)?; let [ptr, len] = this.check_shim(abi, Conv::C , link_name, args)?;
let ptr = this.read_pointer(ptr)?; let ptr = this.read_pointer(ptr)?;
let len = this.read_target_usize(len)?; let len = this.read_target_usize(len)?;
this.gen_random(ptr, len)?; this.gen_random(ptr, len)?;
@ -848,12 +848,12 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
); );
} }
// This function looks and behaves excatly like miri_start_unwind. // This function looks and behaves excatly like miri_start_unwind.
let [payload] = this.check_shim(abi, ExternAbi::C { unwind: true }, link_name, args)?; let [payload] = this.check_shim(abi, Conv::C, link_name, args)?;
this.handle_miri_start_unwind(payload)?; this.handle_miri_start_unwind(payload)?;
return interp_ok(EmulateItemResult::NeedsUnwind); return interp_ok(EmulateItemResult::NeedsUnwind);
} }
"getuid" => { "getuid" => {
let [] = this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; let [] = this.check_shim(abi, Conv::C , link_name, args)?;
// For now, just pretend we always have this fixed UID. // For now, just pretend we always have this fixed UID.
this.write_int(UID, dest)?; this.write_int(UID, dest)?;
} }
@ -862,7 +862,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
// These shims are enabled only when the caller is in the standard library. // These shims are enabled only when the caller is in the standard library.
"pthread_attr_getguardsize" "pthread_attr_getguardsize"
if this.frame_in_std() => { if this.frame_in_std() => {
let [_attr, guard_size] = this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; let [_attr, guard_size] = this.check_shim(abi, Conv::C , link_name, args)?;
let guard_size = this.deref_pointer(guard_size)?; let guard_size = this.deref_pointer(guard_size)?;
let guard_size_layout = this.libc_ty_layout("size_t"); let guard_size_layout = this.libc_ty_layout("size_t");
this.write_scalar(Scalar::from_uint(this.machine.page_size, guard_size_layout.size), &guard_size)?; this.write_scalar(Scalar::from_uint(this.machine.page_size, guard_size_layout.size), &guard_size)?;
@ -874,12 +874,12 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
| "pthread_attr_init" | "pthread_attr_init"
| "pthread_attr_destroy" | "pthread_attr_destroy"
if this.frame_in_std() => { if this.frame_in_std() => {
let [_] = this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; let [_] = this.check_shim(abi, Conv::C , link_name, args)?;
this.write_null(dest)?; this.write_null(dest)?;
} }
| "pthread_attr_setstacksize" | "pthread_attr_setstacksize"
if this.frame_in_std() => { if this.frame_in_std() => {
let [_, _] = this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; let [_, _] = this.check_shim(abi, Conv::C , link_name, args)?;
this.write_null(dest)?; this.write_null(dest)?;
} }
@ -888,7 +888,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
// We don't support "pthread_attr_setstack", so we just pretend all stacks have the same values here. // We don't support "pthread_attr_setstack", so we just pretend all stacks have the same values here.
// Hence we can mostly ignore the input `attr_place`. // Hence we can mostly ignore the input `attr_place`.
let [attr_place, addr_place, size_place] = let [attr_place, addr_place, size_place] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C , link_name, args)?;
let _attr_place = this.deref_pointer_as(attr_place, this.libc_ty_layout("pthread_attr_t"))?; let _attr_place = this.deref_pointer_as(attr_place, this.libc_ty_layout("pthread_attr_t"))?;
let addr_place = this.deref_pointer(addr_place)?; let addr_place = this.deref_pointer(addr_place)?;
let size_place = this.deref_pointer(size_place)?; let size_place = this.deref_pointer(size_place)?;
@ -909,13 +909,13 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
| "signal" | "signal"
| "sigaltstack" | "sigaltstack"
if this.frame_in_std() => { if this.frame_in_std() => {
let [_, _] = this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; let [_, _] = this.check_shim(abi, Conv::C , link_name, args)?;
this.write_null(dest)?; this.write_null(dest)?;
} }
| "sigaction" | "sigaction"
| "mprotect" | "mprotect"
if this.frame_in_std() => { if this.frame_in_std() => {
let [_, _, _] = this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; let [_, _, _] = this.check_shim(abi, Conv::C , link_name, args)?;
this.write_null(dest)?; this.write_null(dest)?;
} }
@ -923,7 +923,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
if this.frame_in_std() => { if this.frame_in_std() => {
// getpwuid_r is the standard name, __posix_getpwuid_r is used on solarish // getpwuid_r is the standard name, __posix_getpwuid_r is used on solarish
let [uid, pwd, buf, buflen, result] = let [uid, pwd, buf, buflen, result] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C , link_name, args)?;
this.check_no_isolation("`getpwuid_r`")?; this.check_no_isolation("`getpwuid_r`")?;
let uid = this.read_scalar(uid)?.to_u32()?; let uid = this.read_scalar(uid)?.to_u32()?;

View file

@ -1,5 +1,6 @@
use rustc_abi::ExternAbi; use rustc_middle::ty::Ty;
use rustc_span::Symbol; use rustc_span::Symbol;
use rustc_target::callconv::{Conv, FnAbi};
use crate::shims::unix::*; use crate::shims::unix::*;
use crate::*; use crate::*;
@ -13,7 +14,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
fn emulate_foreign_item_inner( fn emulate_foreign_item_inner(
&mut self, &mut self,
link_name: Symbol, link_name: Symbol,
abi: ExternAbi, abi: &FnAbi<'tcx, Ty<'tcx>>,
args: &[OpTy<'tcx>], args: &[OpTy<'tcx>],
dest: &MPlaceTy<'tcx>, dest: &MPlaceTy<'tcx>,
) -> InterpResult<'tcx, EmulateItemResult> { ) -> InterpResult<'tcx, EmulateItemResult> {
@ -22,7 +23,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
// Threading // Threading
"pthread_set_name_np" => { "pthread_set_name_np" => {
let [thread, name] = let [thread, name] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C, link_name, args)?;
let max_len = usize::MAX; // FreeBSD does not seem to have a limit. let max_len = usize::MAX; // FreeBSD does not seem to have a limit.
// FreeBSD's pthread_set_name_np does not return anything. // FreeBSD's pthread_set_name_np does not return anything.
this.pthread_setname_np( this.pthread_setname_np(
@ -34,7 +35,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
} }
"pthread_get_name_np" => { "pthread_get_name_np" => {
let [thread, name, len] = let [thread, name, len] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C, link_name, args)?;
// FreeBSD's pthread_get_name_np does not return anything // FreeBSD's pthread_get_name_np does not return anything
// and uses strlcpy, which truncates the resulting value, // and uses strlcpy, which truncates the resulting value,
// but always adds a null terminator (except for zero-sized buffers). // but always adds a null terminator (except for zero-sized buffers).
@ -52,32 +53,32 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
// since freebsd 12 the former form can be expected. // since freebsd 12 the former form can be expected.
"stat" | "stat@FBSD_1.0" => { "stat" | "stat@FBSD_1.0" => {
let [path, buf] = let [path, buf] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C, link_name, args)?;
let result = this.macos_fbsd_solaris_stat(path, buf)?; let result = this.macos_fbsd_solaris_stat(path, buf)?;
this.write_scalar(result, dest)?; this.write_scalar(result, dest)?;
} }
"lstat" | "lstat@FBSD_1.0" => { "lstat" | "lstat@FBSD_1.0" => {
let [path, buf] = let [path, buf] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C, link_name, args)?;
let result = this.macos_fbsd_solaris_lstat(path, buf)?; let result = this.macos_fbsd_solaris_lstat(path, buf)?;
this.write_scalar(result, dest)?; this.write_scalar(result, dest)?;
} }
"fstat" | "fstat@FBSD_1.0" => { "fstat" | "fstat@FBSD_1.0" => {
let [fd, buf] = let [fd, buf] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C, link_name, args)?;
let result = this.macos_fbsd_solaris_fstat(fd, buf)?; let result = this.macos_fbsd_solaris_fstat(fd, buf)?;
this.write_scalar(result, dest)?; this.write_scalar(result, dest)?;
} }
"readdir_r" | "readdir_r@FBSD_1.0" => { "readdir_r" | "readdir_r@FBSD_1.0" => {
let [dirp, entry, result] = let [dirp, entry, result] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C, link_name, args)?;
let result = this.macos_fbsd_readdir_r(dirp, entry, result)?; let result = this.macos_fbsd_readdir_r(dirp, entry, result)?;
this.write_scalar(result, dest)?; this.write_scalar(result, dest)?;
} }
// Miscellaneous // Miscellaneous
"__error" => { "__error" => {
let [] = this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; let [] = this.check_shim(abi, Conv::C, link_name, args)?;
let errno_place = this.last_error_place()?; let errno_place = this.last_error_place()?;
this.write_scalar(errno_place.to_ref(this).to_scalar(), dest)?; this.write_scalar(errno_place.to_ref(this).to_scalar(), dest)?;
} }
@ -86,7 +87,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
// These shims are enabled only when the caller is in the standard library. // These shims are enabled only when the caller is in the standard library.
"pthread_attr_get_np" if this.frame_in_std() => { "pthread_attr_get_np" if this.frame_in_std() => {
let [_thread, _attr] = let [_thread, _attr] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C, link_name, args)?;
this.write_null(dest)?; this.write_null(dest)?;
} }

View file

@ -1,5 +1,6 @@
use rustc_abi::ExternAbi; use rustc_middle::ty::Ty;
use rustc_span::Symbol; use rustc_span::Symbol;
use rustc_target::callconv::{Conv, FnAbi};
use self::shims::unix::linux::mem::EvalContextExt as _; use self::shims::unix::linux::mem::EvalContextExt as _;
use self::shims::unix::linux_like::epoll::EvalContextExt as _; use self::shims::unix::linux_like::epoll::EvalContextExt as _;
@ -24,7 +25,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
fn emulate_foreign_item_inner( fn emulate_foreign_item_inner(
&mut self, &mut self,
link_name: Symbol, link_name: Symbol,
abi: ExternAbi, abi: &FnAbi<'tcx, Ty<'tcx>>,
args: &[OpTy<'tcx>], args: &[OpTy<'tcx>],
dest: &MPlaceTy<'tcx>, dest: &MPlaceTy<'tcx>,
) -> InterpResult<'tcx, EmulateItemResult> { ) -> InterpResult<'tcx, EmulateItemResult> {
@ -36,19 +37,19 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
// File related shims // File related shims
"readdir64" => { "readdir64" => {
let [dirp] = let [dirp] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C, link_name, args)?;
let result = this.linux_readdir64(dirp)?; let result = this.linux_readdir64(dirp)?;
this.write_scalar(result, dest)?; this.write_scalar(result, dest)?;
} }
"sync_file_range" => { "sync_file_range" => {
let [fd, offset, nbytes, flags] = let [fd, offset, nbytes, flags] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C, link_name, args)?;
let result = this.sync_file_range(fd, offset, nbytes, flags)?; let result = this.sync_file_range(fd, offset, nbytes, flags)?;
this.write_scalar(result, dest)?; this.write_scalar(result, dest)?;
} }
"statx" => { "statx" => {
let [dirfd, pathname, flags, mask, statxbuf] = let [dirfd, pathname, flags, mask, statxbuf] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C, link_name, args)?;
let result = this.linux_statx(dirfd, pathname, flags, mask, statxbuf)?; let result = this.linux_statx(dirfd, pathname, flags, mask, statxbuf)?;
this.write_scalar(result, dest)?; this.write_scalar(result, dest)?;
} }
@ -56,24 +57,24 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
// epoll, eventfd // epoll, eventfd
"epoll_create1" => { "epoll_create1" => {
let [flag] = let [flag] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C, link_name, args)?;
let result = this.epoll_create1(flag)?; let result = this.epoll_create1(flag)?;
this.write_scalar(result, dest)?; this.write_scalar(result, dest)?;
} }
"epoll_ctl" => { "epoll_ctl" => {
let [epfd, op, fd, event] = let [epfd, op, fd, event] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C, link_name, args)?;
let result = this.epoll_ctl(epfd, op, fd, event)?; let result = this.epoll_ctl(epfd, op, fd, event)?;
this.write_scalar(result, dest)?; this.write_scalar(result, dest)?;
} }
"epoll_wait" => { "epoll_wait" => {
let [epfd, events, maxevents, timeout] = let [epfd, events, maxevents, timeout] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C, link_name, args)?;
this.epoll_wait(epfd, events, maxevents, timeout, dest)?; this.epoll_wait(epfd, events, maxevents, timeout, dest)?;
} }
"eventfd" => { "eventfd" => {
let [val, flag] = let [val, flag] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C, link_name, args)?;
let result = this.eventfd(val, flag)?; let result = this.eventfd(val, flag)?;
this.write_scalar(result, dest)?; this.write_scalar(result, dest)?;
} }
@ -81,7 +82,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
// Threading // Threading
"pthread_setname_np" => { "pthread_setname_np" => {
let [thread, name] = let [thread, name] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C, link_name, args)?;
let res = match this.pthread_setname_np( let res = match this.pthread_setname_np(
this.read_scalar(thread)?, this.read_scalar(thread)?,
this.read_scalar(name)?, this.read_scalar(name)?,
@ -97,7 +98,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
} }
"pthread_getname_np" => { "pthread_getname_np" => {
let [thread, name, len] = let [thread, name, len] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C, link_name, args)?;
// The function's behavior isn't portable between platforms. // The function's behavior isn't portable between platforms.
// In case of glibc, the length of the output buffer must // In case of glibc, the length of the output buffer must
// be not shorter than TASK_COMM_LEN. // be not shorter than TASK_COMM_LEN.
@ -120,7 +121,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
this.write_scalar(res, dest)?; this.write_scalar(res, dest)?;
} }
"gettid" => { "gettid" => {
let [] = this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; let [] = this.check_shim(abi, Conv::C, link_name, args)?;
let result = this.linux_gettid()?; let result = this.linux_gettid()?;
this.write_scalar(result, dest)?; this.write_scalar(result, dest)?;
} }
@ -133,35 +134,35 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
// Miscellaneous // Miscellaneous
"mmap64" => { "mmap64" => {
let [addr, length, prot, flags, fd, offset] = let [addr, length, prot, flags, fd, offset] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C, link_name, args)?;
let offset = this.read_scalar(offset)?.to_i64()?; let offset = this.read_scalar(offset)?.to_i64()?;
let ptr = this.mmap(addr, length, prot, flags, fd, offset.into())?; let ptr = this.mmap(addr, length, prot, flags, fd, offset.into())?;
this.write_scalar(ptr, dest)?; this.write_scalar(ptr, dest)?;
} }
"mremap" => { "mremap" => {
let [old_address, old_size, new_size, flags] = let [old_address, old_size, new_size, flags] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C, link_name, args)?;
let ptr = this.mremap(old_address, old_size, new_size, flags)?; let ptr = this.mremap(old_address, old_size, new_size, flags)?;
this.write_scalar(ptr, dest)?; this.write_scalar(ptr, dest)?;
} }
"__xpg_strerror_r" => { "__xpg_strerror_r" => {
let [errnum, buf, buflen] = let [errnum, buf, buflen] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C, link_name, args)?;
let result = this.strerror_r(errnum, buf, buflen)?; let result = this.strerror_r(errnum, buf, buflen)?;
this.write_scalar(result, dest)?; this.write_scalar(result, dest)?;
} }
"__errno_location" => { "__errno_location" => {
let [] = this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; let [] = this.check_shim(abi, Conv::C, link_name, args)?;
let errno_place = this.last_error_place()?; let errno_place = this.last_error_place()?;
this.write_scalar(errno_place.to_ref(this).to_scalar(), dest)?; this.write_scalar(errno_place.to_ref(this).to_scalar(), dest)?;
} }
"__libc_current_sigrtmin" => { "__libc_current_sigrtmin" => {
let [] = this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; let [] = this.check_shim(abi, Conv::C, link_name, args)?;
this.write_int(SIGRTMIN, dest)?; this.write_int(SIGRTMIN, dest)?;
} }
"__libc_current_sigrtmax" => { "__libc_current_sigrtmax" => {
let [] = this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; let [] = this.check_shim(abi, Conv::C, link_name, args)?;
this.write_int(SIGRTMAX, dest)?; this.write_int(SIGRTMAX, dest)?;
} }
@ -170,7 +171,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
// These shims are enabled only when the caller is in the standard library. // These shims are enabled only when the caller is in the standard library.
"pthread_getattr_np" if this.frame_in_std() => { "pthread_getattr_np" if this.frame_in_std() => {
let [_thread, _attr] = let [_thread, _attr] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C, link_name, args)?;
this.write_null(dest)?; this.write_null(dest)?;
} }

View file

@ -1,5 +1,7 @@
use rustc_abi::ExternAbi; use rustc_middle::ty::Ty;
use rustc_span::Symbol; use rustc_span::Symbol;
use rustc_target::callconv::{Conv, FnAbi};
use crate::helpers::check_min_arg_count; use crate::helpers::check_min_arg_count;
use crate::shims::unix::linux_like::eventfd::EvalContextExt as _; use crate::shims::unix::linux_like::eventfd::EvalContextExt as _;
@ -9,13 +11,13 @@ use crate::*;
pub fn syscall<'tcx>( pub fn syscall<'tcx>(
ecx: &mut MiriInterpCx<'tcx>, ecx: &mut MiriInterpCx<'tcx>,
link_name: Symbol, link_name: Symbol,
abi: ExternAbi, abi: &FnAbi<'tcx, Ty<'tcx>>,
args: &[OpTy<'tcx>], args: &[OpTy<'tcx>],
dest: &MPlaceTy<'tcx>, dest: &MPlaceTy<'tcx>,
) -> InterpResult<'tcx> { ) -> InterpResult<'tcx> {
// We do not use `check_shim` here because `syscall` is variadic. The argument // We do not use `check_shim` here because `syscall` is variadic. The argument
// count is checked bellow. // count is checked bellow.
ecx.check_abi_and_shim_symbol_clash(abi, ExternAbi::C { unwind: false }, link_name)?; ecx.check_abi_and_shim_symbol_clash(abi, Conv::C, link_name)?;
// The syscall variadic function is legal to call with more arguments than needed, // The syscall variadic function is legal to call with more arguments than needed,
// extra arguments are simply ignored. The important check is that when we use an // extra arguments are simply ignored. The important check is that when we use an
// argument, we have to also check all arguments *before* it to ensure that they // argument, we have to also check all arguments *before* it to ensure that they

View file

@ -1,5 +1,6 @@
use rustc_abi::ExternAbi; use rustc_middle::ty::Ty;
use rustc_span::Symbol; use rustc_span::Symbol;
use rustc_target::callconv::{Conv, FnAbi};
use super::sync::EvalContextExt as _; use super::sync::EvalContextExt as _;
use crate::shims::unix::*; use crate::shims::unix::*;
@ -14,7 +15,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
fn emulate_foreign_item_inner( fn emulate_foreign_item_inner(
&mut self, &mut self,
link_name: Symbol, link_name: Symbol,
abi: ExternAbi, abi: &FnAbi<'tcx, Ty<'tcx>>,
args: &[OpTy<'tcx>], args: &[OpTy<'tcx>],
dest: &MPlaceTy<'tcx>, dest: &MPlaceTy<'tcx>,
) -> InterpResult<'tcx, EmulateItemResult> { ) -> InterpResult<'tcx, EmulateItemResult> {
@ -25,7 +26,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
match link_name.as_str() { match link_name.as_str() {
// errno // errno
"__error" => { "__error" => {
let [] = this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; let [] = this.check_shim(abi, Conv::C, link_name, args)?;
let errno_place = this.last_error_place()?; let errno_place = this.last_error_place()?;
this.write_scalar(errno_place.to_ref(this).to_scalar(), dest)?; this.write_scalar(errno_place.to_ref(this).to_scalar(), dest)?;
} }
@ -33,50 +34,50 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
// File related shims // File related shims
"close$NOCANCEL" => { "close$NOCANCEL" => {
let [result] = let [result] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C, link_name, args)?;
let result = this.close(result)?; let result = this.close(result)?;
this.write_scalar(result, dest)?; this.write_scalar(result, dest)?;
} }
"stat" | "stat64" | "stat$INODE64" => { "stat" | "stat64" | "stat$INODE64" => {
let [path, buf] = let [path, buf] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C, link_name, args)?;
let result = this.macos_fbsd_solaris_stat(path, buf)?; let result = this.macos_fbsd_solaris_stat(path, buf)?;
this.write_scalar(result, dest)?; this.write_scalar(result, dest)?;
} }
"lstat" | "lstat64" | "lstat$INODE64" => { "lstat" | "lstat64" | "lstat$INODE64" => {
let [path, buf] = let [path, buf] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C, link_name, args)?;
let result = this.macos_fbsd_solaris_lstat(path, buf)?; let result = this.macos_fbsd_solaris_lstat(path, buf)?;
this.write_scalar(result, dest)?; this.write_scalar(result, dest)?;
} }
"fstat" | "fstat64" | "fstat$INODE64" => { "fstat" | "fstat64" | "fstat$INODE64" => {
let [fd, buf] = let [fd, buf] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C, link_name, args)?;
let result = this.macos_fbsd_solaris_fstat(fd, buf)?; let result = this.macos_fbsd_solaris_fstat(fd, buf)?;
this.write_scalar(result, dest)?; this.write_scalar(result, dest)?;
} }
"opendir$INODE64" => { "opendir$INODE64" => {
let [name] = let [name] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C, link_name, args)?;
let result = this.opendir(name)?; let result = this.opendir(name)?;
this.write_scalar(result, dest)?; this.write_scalar(result, dest)?;
} }
"readdir_r" | "readdir_r$INODE64" => { "readdir_r" | "readdir_r$INODE64" => {
let [dirp, entry, result] = let [dirp, entry, result] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C, link_name, args)?;
let result = this.macos_fbsd_readdir_r(dirp, entry, result)?; let result = this.macos_fbsd_readdir_r(dirp, entry, result)?;
this.write_scalar(result, dest)?; this.write_scalar(result, dest)?;
} }
"realpath$DARWIN_EXTSN" => { "realpath$DARWIN_EXTSN" => {
let [path, resolved_path] = let [path, resolved_path] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C, link_name, args)?;
let result = this.realpath(path, resolved_path)?; let result = this.realpath(path, resolved_path)?;
this.write_scalar(result, dest)?; this.write_scalar(result, dest)?;
} }
// Environment related shims // Environment related shims
"_NSGetEnviron" => { "_NSGetEnviron" => {
let [] = this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; let [] = this.check_shim(abi, Conv::C, link_name, args)?;
let environ = this.machine.env_vars.unix().environ(); let environ = this.machine.env_vars.unix().environ();
this.write_pointer(environ, dest)?; this.write_pointer(environ, dest)?;
} }
@ -84,7 +85,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
// Random data generation // Random data generation
"CCRandomGenerateBytes" => { "CCRandomGenerateBytes" => {
let [bytes, count] = let [bytes, count] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C, link_name, args)?;
let bytes = this.read_pointer(bytes)?; let bytes = this.read_pointer(bytes)?;
let count = this.read_target_usize(count)?; let count = this.read_target_usize(count)?;
let success = this.eval_libc_i32("kCCSuccess"); let success = this.eval_libc_i32("kCCSuccess");
@ -94,30 +95,30 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
// Time related shims // Time related shims
"mach_absolute_time" => { "mach_absolute_time" => {
let [] = this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; let [] = this.check_shim(abi, Conv::C, link_name, args)?;
let result = this.mach_absolute_time()?; let result = this.mach_absolute_time()?;
this.write_scalar(result, dest)?; this.write_scalar(result, dest)?;
} }
"mach_timebase_info" => { "mach_timebase_info" => {
let [info] = let [info] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C, link_name, args)?;
let result = this.mach_timebase_info(info)?; let result = this.mach_timebase_info(info)?;
this.write_scalar(result, dest)?; this.write_scalar(result, dest)?;
} }
// Access to command-line arguments // Access to command-line arguments
"_NSGetArgc" => { "_NSGetArgc" => {
let [] = this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; let [] = this.check_shim(abi, Conv::C, link_name, args)?;
this.write_pointer(this.machine.argc.expect("machine must be initialized"), dest)?; this.write_pointer(this.machine.argc.expect("machine must be initialized"), dest)?;
} }
"_NSGetArgv" => { "_NSGetArgv" => {
let [] = this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; let [] = this.check_shim(abi, Conv::C, link_name, args)?;
this.write_pointer(this.machine.argv.expect("machine must be initialized"), dest)?; this.write_pointer(this.machine.argv.expect("machine must be initialized"), dest)?;
} }
"_NSGetExecutablePath" => { "_NSGetExecutablePath" => {
let [buf, bufsize] = let [buf, bufsize] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C, link_name, args)?;
this.check_no_isolation("`_NSGetExecutablePath`")?; this.check_no_isolation("`_NSGetExecutablePath`")?;
let buf_ptr = this.read_pointer(buf)?; let buf_ptr = this.read_pointer(buf)?;
@ -143,7 +144,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
// Thread-local storage // Thread-local storage
"_tlv_atexit" => { "_tlv_atexit" => {
let [dtor, data] = let [dtor, data] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C, link_name, args)?;
let dtor = this.read_pointer(dtor)?; let dtor = this.read_pointer(dtor)?;
let dtor = this.get_ptr_fn(dtor)?.as_instance()?; let dtor = this.get_ptr_fn(dtor)?.as_instance()?;
let data = this.read_scalar(data)?; let data = this.read_scalar(data)?;
@ -154,14 +155,14 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
// Querying system information // Querying system information
"pthread_get_stackaddr_np" => { "pthread_get_stackaddr_np" => {
let [thread] = let [thread] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C, link_name, args)?;
this.read_target_usize(thread)?; this.read_target_usize(thread)?;
let stack_addr = Scalar::from_uint(this.machine.stack_addr, this.pointer_size()); let stack_addr = Scalar::from_uint(this.machine.stack_addr, this.pointer_size());
this.write_scalar(stack_addr, dest)?; this.write_scalar(stack_addr, dest)?;
} }
"pthread_get_stacksize_np" => { "pthread_get_stacksize_np" => {
let [thread] = let [thread] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C, link_name, args)?;
this.read_target_usize(thread)?; this.read_target_usize(thread)?;
let stack_size = Scalar::from_uint(this.machine.stack_size, this.pointer_size()); let stack_size = Scalar::from_uint(this.machine.stack_size, this.pointer_size());
this.write_scalar(stack_size, dest)?; this.write_scalar(stack_size, dest)?;
@ -170,7 +171,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
// Threading // Threading
"pthread_setname_np" => { "pthread_setname_np" => {
let [name] = let [name] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C, link_name, args)?;
// The real implementation has logic in two places: // The real implementation has logic in two places:
// * in userland at https://github.com/apple-oss-distributions/libpthread/blob/c032e0b076700a0a47db75528a282b8d3a06531a/src/pthread.c#L1178-L1200, // * in userland at https://github.com/apple-oss-distributions/libpthread/blob/c032e0b076700a0a47db75528a282b8d3a06531a/src/pthread.c#L1178-L1200,
@ -198,7 +199,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
} }
"pthread_getname_np" => { "pthread_getname_np" => {
let [thread, name, len] = let [thread, name, len] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C, link_name, args)?;
// The function's behavior isn't portable between platforms. // The function's behavior isn't portable between platforms.
// In case of macOS, a truncated name (due to a too small buffer) // In case of macOS, a truncated name (due to a too small buffer)
@ -224,27 +225,27 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
"os_unfair_lock_lock" => { "os_unfair_lock_lock" => {
let [lock_op] = let [lock_op] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C, link_name, args)?;
this.os_unfair_lock_lock(lock_op)?; this.os_unfair_lock_lock(lock_op)?;
} }
"os_unfair_lock_trylock" => { "os_unfair_lock_trylock" => {
let [lock_op] = let [lock_op] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C, link_name, args)?;
this.os_unfair_lock_trylock(lock_op, dest)?; this.os_unfair_lock_trylock(lock_op, dest)?;
} }
"os_unfair_lock_unlock" => { "os_unfair_lock_unlock" => {
let [lock_op] = let [lock_op] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C, link_name, args)?;
this.os_unfair_lock_unlock(lock_op)?; this.os_unfair_lock_unlock(lock_op)?;
} }
"os_unfair_lock_assert_owner" => { "os_unfair_lock_assert_owner" => {
let [lock_op] = let [lock_op] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C, link_name, args)?;
this.os_unfair_lock_assert_owner(lock_op)?; this.os_unfair_lock_assert_owner(lock_op)?;
} }
"os_unfair_lock_assert_not_owner" => { "os_unfair_lock_assert_not_owner" => {
let [lock_op] = let [lock_op] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C, link_name, args)?;
this.os_unfair_lock_assert_not_owner(lock_op)?; this.os_unfair_lock_assert_not_owner(lock_op)?;
} }

View file

@ -1,5 +1,6 @@
use rustc_abi::ExternAbi; use rustc_middle::ty::Ty;
use rustc_span::Symbol; use rustc_span::Symbol;
use rustc_target::callconv::{Conv, FnAbi};
use crate::shims::unix::foreign_items::EvalContextExt as _; use crate::shims::unix::foreign_items::EvalContextExt as _;
use crate::shims::unix::*; use crate::shims::unix::*;
@ -14,7 +15,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
fn emulate_foreign_item_inner( fn emulate_foreign_item_inner(
&mut self, &mut self,
link_name: Symbol, link_name: Symbol,
abi: ExternAbi, abi: &FnAbi<'tcx, Ty<'tcx>>,
args: &[OpTy<'tcx>], args: &[OpTy<'tcx>],
dest: &MPlaceTy<'tcx>, dest: &MPlaceTy<'tcx>,
) -> InterpResult<'tcx, EmulateItemResult> { ) -> InterpResult<'tcx, EmulateItemResult> {
@ -23,7 +24,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
// Threading // Threading
"pthread_setname_np" => { "pthread_setname_np" => {
let [thread, name] = let [thread, name] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C, link_name, args)?;
// THREAD_NAME_MAX allows a thread name of 31+1 length // THREAD_NAME_MAX allows a thread name of 31+1 length
// https://github.com/illumos/illumos-gate/blob/7671517e13b8123748eda4ef1ee165c6d9dba7fe/usr/src/uts/common/sys/thread.h#L613 // https://github.com/illumos/illumos-gate/blob/7671517e13b8123748eda4ef1ee165c6d9dba7fe/usr/src/uts/common/sys/thread.h#L613
let max_len = 32; let max_len = 32;
@ -42,7 +43,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
} }
"pthread_getname_np" => { "pthread_getname_np" => {
let [thread, name, len] = let [thread, name, len] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C, link_name, args)?;
// See https://illumos.org/man/3C/pthread_getname_np for the error codes. // See https://illumos.org/man/3C/pthread_getname_np for the error codes.
let res = match this.pthread_getname_np( let res = match this.pthread_getname_np(
this.read_scalar(thread)?, this.read_scalar(thread)?,
@ -60,33 +61,33 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
// File related shims // File related shims
"stat" | "stat64" => { "stat" | "stat64" => {
let [path, buf] = let [path, buf] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C, link_name, args)?;
let result = this.macos_fbsd_solaris_stat(path, buf)?; let result = this.macos_fbsd_solaris_stat(path, buf)?;
this.write_scalar(result, dest)?; this.write_scalar(result, dest)?;
} }
"lstat" | "lstat64" => { "lstat" | "lstat64" => {
let [path, buf] = let [path, buf] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C, link_name, args)?;
let result = this.macos_fbsd_solaris_lstat(path, buf)?; let result = this.macos_fbsd_solaris_lstat(path, buf)?;
this.write_scalar(result, dest)?; this.write_scalar(result, dest)?;
} }
"fstat" | "fstat64" => { "fstat" | "fstat64" => {
let [fd, buf] = let [fd, buf] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C, link_name, args)?;
let result = this.macos_fbsd_solaris_fstat(fd, buf)?; let result = this.macos_fbsd_solaris_fstat(fd, buf)?;
this.write_scalar(result, dest)?; this.write_scalar(result, dest)?;
} }
// Miscellaneous // Miscellaneous
"___errno" => { "___errno" => {
let [] = this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; let [] = this.check_shim(abi, Conv::C, link_name, args)?;
let errno_place = this.last_error_place()?; let errno_place = this.last_error_place()?;
this.write_scalar(errno_place.to_ref(this).to_scalar(), dest)?; this.write_scalar(errno_place.to_ref(this).to_scalar(), dest)?;
} }
"stack_getbounds" => { "stack_getbounds" => {
let [stack] = let [stack] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C, link_name, args)?;
let stack = this.deref_pointer_as(stack, this.libc_ty_layout("stack_t"))?; let stack = this.deref_pointer_as(stack, this.libc_ty_layout("stack_t"))?;
this.write_int_fields_named( this.write_int_fields_named(
@ -105,7 +106,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
"pset_info" => { "pset_info" => {
let [pset, tpe, cpus, list] = let [pset, tpe, cpus, list] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C, link_name, args)?;
// We do not need to handle the current process cpu mask, available_parallelism // We do not need to handle the current process cpu mask, available_parallelism
// implementation pass null anyway. We only care for the number of // implementation pass null anyway. We only care for the number of
// cpus. // cpus.
@ -135,7 +136,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
"__sysconf_xpg7" => { "__sysconf_xpg7" => {
let [val] = let [val] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C, link_name, args)?;
let result = this.sysconf(val)?; let result = this.sysconf(val)?;
this.write_scalar(result, dest)?; this.write_scalar(result, dest)?;
} }

View file

@ -1,5 +1,6 @@
use rustc_abi::ExternAbi; use rustc_middle::ty::Ty;
use rustc_span::Symbol; use rustc_span::Symbol;
use rustc_target::callconv::{Conv, FnAbi};
use crate::shims::alloc::EvalContextExt as _; use crate::shims::alloc::EvalContextExt as _;
use crate::*; use crate::*;
@ -13,7 +14,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
fn emulate_foreign_item_inner( fn emulate_foreign_item_inner(
&mut self, &mut self,
link_name: Symbol, link_name: Symbol,
abi: ExternAbi, abi: &FnAbi<'tcx, Ty<'tcx>>,
args: &[OpTy<'tcx>], args: &[OpTy<'tcx>],
dest: &MPlaceTy<'tcx>, dest: &MPlaceTy<'tcx>,
) -> InterpResult<'tcx, EmulateItemResult> { ) -> InterpResult<'tcx, EmulateItemResult> {
@ -22,13 +23,13 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
// Allocation // Allocation
"posix_memalign" => { "posix_memalign" => {
let [memptr, align, size] = let [memptr, align, size] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C, link_name, args)?;
let result = this.posix_memalign(memptr, align, size)?; let result = this.posix_memalign(memptr, align, size)?;
this.write_scalar(result, dest)?; this.write_scalar(result, dest)?;
} }
"aligned_alloc" => { "aligned_alloc" => {
let [align, size] = let [align, size] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C, link_name, args)?;
let res = this.aligned_alloc(align, size)?; let res = this.aligned_alloc(align, size)?;
this.write_pointer(res, dest)?; this.write_pointer(res, dest)?;
} }

View file

@ -2,8 +2,10 @@ use std::ffi::OsStr;
use std::path::{self, Path, PathBuf}; use std::path::{self, Path, PathBuf};
use std::{io, iter, str}; use std::{io, iter, str};
use rustc_abi::{Align, ExternAbi, Size}; use rustc_abi::{Align, Size};
use rustc_middle::ty::Ty;
use rustc_span::Symbol; use rustc_span::Symbol;
use rustc_target::callconv::{Conv, FnAbi};
use self::shims::windows::handle::{Handle, PseudoHandle}; use self::shims::windows::handle::{Handle, PseudoHandle};
use crate::shims::os_str::bytes_to_os_str; use crate::shims::os_str::bytes_to_os_str;
@ -83,12 +85,18 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
fn emulate_foreign_item_inner( fn emulate_foreign_item_inner(
&mut self, &mut self,
link_name: Symbol, link_name: Symbol,
abi: ExternAbi, abi: &FnAbi<'tcx, Ty<'tcx>>,
args: &[OpTy<'tcx>], args: &[OpTy<'tcx>],
dest: &MPlaceTy<'tcx>, dest: &MPlaceTy<'tcx>,
) -> InterpResult<'tcx, EmulateItemResult> { ) -> InterpResult<'tcx, EmulateItemResult> {
let this = self.eval_context_mut(); let this = self.eval_context_mut();
// According to
// https://github.com/rust-lang/rust/blob/fb00adbdb69266f10df95a4527b767b0ad35ea48/compiler/rustc_target/src/spec/mod.rs#L2766-L2768,
// x86-32 Windows uses a different calling convention than other Windows targets
// for the "system" ABI.
let sys_conv = if this.tcx.sess.target.arch == "x86" { Conv::X86Stdcall } else { Conv::C };
// See `fn emulate_foreign_item_inner` in `shims/foreign_items.rs` for the general pattern. // See `fn emulate_foreign_item_inner` in `shims/foreign_items.rs` for the general pattern.
// Windows API stubs. // Windows API stubs.
@ -101,49 +109,49 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
// Environment related shims // Environment related shims
"GetEnvironmentVariableW" => { "GetEnvironmentVariableW" => {
let [name, buf, size] = let [name, buf, size] =
this.check_shim(abi, ExternAbi::System { unwind: false }, link_name, args)?; this.check_shim(abi, sys_conv, link_name, args)?;
let result = this.GetEnvironmentVariableW(name, buf, size)?; let result = this.GetEnvironmentVariableW(name, buf, size)?;
this.write_scalar(result, dest)?; this.write_scalar(result, dest)?;
} }
"SetEnvironmentVariableW" => { "SetEnvironmentVariableW" => {
let [name, value] = let [name, value] =
this.check_shim(abi, ExternAbi::System { unwind: false }, link_name, args)?; this.check_shim(abi, sys_conv, link_name, args)?;
let result = this.SetEnvironmentVariableW(name, value)?; let result = this.SetEnvironmentVariableW(name, value)?;
this.write_scalar(result, dest)?; this.write_scalar(result, dest)?;
} }
"GetEnvironmentStringsW" => { "GetEnvironmentStringsW" => {
let [] = let [] =
this.check_shim(abi, ExternAbi::System { unwind: false }, link_name, args)?; this.check_shim(abi, sys_conv, link_name, args)?;
let result = this.GetEnvironmentStringsW()?; let result = this.GetEnvironmentStringsW()?;
this.write_pointer(result, dest)?; this.write_pointer(result, dest)?;
} }
"FreeEnvironmentStringsW" => { "FreeEnvironmentStringsW" => {
let [env_block] = let [env_block] =
this.check_shim(abi, ExternAbi::System { unwind: false }, link_name, args)?; this.check_shim(abi, sys_conv, link_name, args)?;
let result = this.FreeEnvironmentStringsW(env_block)?; let result = this.FreeEnvironmentStringsW(env_block)?;
this.write_scalar(result, dest)?; this.write_scalar(result, dest)?;
} }
"GetCurrentDirectoryW" => { "GetCurrentDirectoryW" => {
let [size, buf] = let [size, buf] =
this.check_shim(abi, ExternAbi::System { unwind: false }, link_name, args)?; this.check_shim(abi, sys_conv, link_name, args)?;
let result = this.GetCurrentDirectoryW(size, buf)?; let result = this.GetCurrentDirectoryW(size, buf)?;
this.write_scalar(result, dest)?; this.write_scalar(result, dest)?;
} }
"SetCurrentDirectoryW" => { "SetCurrentDirectoryW" => {
let [path] = let [path] =
this.check_shim(abi, ExternAbi::System { unwind: false }, link_name, args)?; this.check_shim(abi, sys_conv, link_name, args)?;
let result = this.SetCurrentDirectoryW(path)?; let result = this.SetCurrentDirectoryW(path)?;
this.write_scalar(result, dest)?; this.write_scalar(result, dest)?;
} }
"GetUserProfileDirectoryW" => { "GetUserProfileDirectoryW" => {
let [token, buf, size] = let [token, buf, size] =
this.check_shim(abi, ExternAbi::System { unwind: false }, link_name, args)?; this.check_shim(abi, sys_conv, link_name, args)?;
let result = this.GetUserProfileDirectoryW(token, buf, size)?; let result = this.GetUserProfileDirectoryW(token, buf, size)?;
this.write_scalar(result, dest)?; this.write_scalar(result, dest)?;
} }
"GetCurrentProcessId" => { "GetCurrentProcessId" => {
let [] = let [] =
this.check_shim(abi, ExternAbi::System { unwind: false }, link_name, args)?; this.check_shim(abi, sys_conv, link_name, args)?;
let result = this.GetCurrentProcessId()?; let result = this.GetCurrentProcessId()?;
this.write_scalar(result, dest)?; this.write_scalar(result, dest)?;
} }
@ -166,7 +174,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
n, n,
byte_offset, byte_offset,
_key, _key,
] = this.check_shim(abi, ExternAbi::System { unwind: false }, link_name, args)?; ] = this.check_shim(abi, sys_conv, link_name, args)?;
let handle = this.read_target_isize(handle)?; let handle = this.read_target_isize(handle)?;
let buf = this.read_pointer(buf)?; let buf = this.read_pointer(buf)?;
let n = this.read_scalar(n)?.to_u32()?; let n = this.read_scalar(n)?.to_u32()?;
@ -218,7 +226,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
} }
"GetFullPathNameW" => { "GetFullPathNameW" => {
let [filename, size, buffer, filepart] = let [filename, size, buffer, filepart] =
this.check_shim(abi, ExternAbi::System { unwind: false }, link_name, args)?; this.check_shim(abi, sys_conv, link_name, args)?;
this.check_no_isolation("`GetFullPathNameW`")?; this.check_no_isolation("`GetFullPathNameW`")?;
let filename = this.read_pointer(filename)?; let filename = this.read_pointer(filename)?;
@ -250,7 +258,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
// Allocation // Allocation
"HeapAlloc" => { "HeapAlloc" => {
let [handle, flags, size] = let [handle, flags, size] =
this.check_shim(abi, ExternAbi::System { unwind: false }, link_name, args)?; this.check_shim(abi, sys_conv, link_name, args)?;
this.read_target_isize(handle)?; this.read_target_isize(handle)?;
let flags = this.read_scalar(flags)?.to_u32()?; let flags = this.read_scalar(flags)?.to_u32()?;
let size = this.read_target_usize(size)?; let size = this.read_target_usize(size)?;
@ -274,7 +282,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
} }
"HeapFree" => { "HeapFree" => {
let [handle, flags, ptr] = let [handle, flags, ptr] =
this.check_shim(abi, ExternAbi::System { unwind: false }, link_name, args)?; this.check_shim(abi, sys_conv, link_name, args)?;
this.read_target_isize(handle)?; this.read_target_isize(handle)?;
this.read_scalar(flags)?.to_u32()?; this.read_scalar(flags)?.to_u32()?;
let ptr = this.read_pointer(ptr)?; let ptr = this.read_pointer(ptr)?;
@ -287,7 +295,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
} }
"HeapReAlloc" => { "HeapReAlloc" => {
let [handle, flags, old_ptr, size] = let [handle, flags, old_ptr, size] =
this.check_shim(abi, ExternAbi::System { unwind: false }, link_name, args)?; this.check_shim(abi, sys_conv, link_name, args)?;
this.read_target_isize(handle)?; this.read_target_isize(handle)?;
this.read_scalar(flags)?.to_u32()?; this.read_scalar(flags)?.to_u32()?;
let old_ptr = this.read_pointer(old_ptr)?; let old_ptr = this.read_pointer(old_ptr)?;
@ -307,7 +315,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
} }
"LocalFree" => { "LocalFree" => {
let [ptr] = let [ptr] =
this.check_shim(abi, ExternAbi::System { unwind: false }, link_name, args)?; this.check_shim(abi, sys_conv, link_name, args)?;
let ptr = this.read_pointer(ptr)?; let ptr = this.read_pointer(ptr)?;
// "If the hMem parameter is NULL, LocalFree ignores the parameter and returns NULL." // "If the hMem parameter is NULL, LocalFree ignores the parameter and returns NULL."
// (https://learn.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-localfree) // (https://learn.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-localfree)
@ -320,13 +328,13 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
// errno // errno
"SetLastError" => { "SetLastError" => {
let [error] = let [error] =
this.check_shim(abi, ExternAbi::System { unwind: false }, link_name, args)?; this.check_shim(abi, sys_conv, link_name, args)?;
let error = this.read_scalar(error)?; let error = this.read_scalar(error)?;
this.set_last_error(error)?; this.set_last_error(error)?;
} }
"GetLastError" => { "GetLastError" => {
let [] = let [] =
this.check_shim(abi, ExternAbi::System { unwind: false }, link_name, args)?; this.check_shim(abi, sys_conv, link_name, args)?;
let last_error = this.get_last_error()?; let last_error = this.get_last_error()?;
this.write_scalar(last_error, dest)?; this.write_scalar(last_error, dest)?;
} }
@ -335,7 +343,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
"GetSystemInfo" => { "GetSystemInfo" => {
// Also called from `page_size` crate. // Also called from `page_size` crate.
let [system_info] = let [system_info] =
this.check_shim(abi, ExternAbi::System { unwind: false }, link_name, args)?; this.check_shim(abi, sys_conv, link_name, args)?;
let system_info = let system_info =
this.deref_pointer_as(system_info, this.windows_ty_layout("SYSTEM_INFO"))?; this.deref_pointer_as(system_info, this.windows_ty_layout("SYSTEM_INFO"))?;
// Initialize with `0`. // Initialize with `0`.
@ -359,13 +367,13 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
// Create key and return it. // Create key and return it.
let [] = let [] =
this.check_shim(abi, ExternAbi::System { unwind: false }, link_name, args)?; this.check_shim(abi, sys_conv, link_name, args)?;
let key = this.machine.tls.create_tls_key(None, dest.layout.size)?; let key = this.machine.tls.create_tls_key(None, dest.layout.size)?;
this.write_scalar(Scalar::from_uint(key, dest.layout.size), dest)?; this.write_scalar(Scalar::from_uint(key, dest.layout.size), dest)?;
} }
"TlsGetValue" => { "TlsGetValue" => {
let [key] = let [key] =
this.check_shim(abi, ExternAbi::System { unwind: false }, link_name, args)?; this.check_shim(abi, sys_conv, link_name, args)?;
let key = u128::from(this.read_scalar(key)?.to_u32()?); let key = u128::from(this.read_scalar(key)?.to_u32()?);
let active_thread = this.active_thread(); let active_thread = this.active_thread();
let ptr = this.machine.tls.load_tls(key, active_thread, this)?; let ptr = this.machine.tls.load_tls(key, active_thread, this)?;
@ -373,7 +381,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
} }
"TlsSetValue" => { "TlsSetValue" => {
let [key, new_ptr] = let [key, new_ptr] =
this.check_shim(abi, ExternAbi::System { unwind: false }, link_name, args)?; this.check_shim(abi, sys_conv, link_name, args)?;
let key = u128::from(this.read_scalar(key)?.to_u32()?); let key = u128::from(this.read_scalar(key)?.to_u32()?);
let active_thread = this.active_thread(); let active_thread = this.active_thread();
let new_data = this.read_scalar(new_ptr)?; let new_data = this.read_scalar(new_ptr)?;
@ -383,8 +391,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
this.write_int(1, dest)?; this.write_int(1, dest)?;
} }
"TlsFree" => { "TlsFree" => {
let [key] = let [key] = this.check_shim(abi, sys_conv, link_name, args)?;
this.check_shim(abi, ExternAbi::System { unwind: false }, link_name, args)?;
let key = u128::from(this.read_scalar(key)?.to_u32()?); let key = u128::from(this.read_scalar(key)?.to_u32()?);
this.machine.tls.delete_tls_key(key)?; this.machine.tls.delete_tls_key(key)?;
@ -395,7 +402,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
// Access to command-line arguments // Access to command-line arguments
"GetCommandLineW" => { "GetCommandLineW" => {
let [] = let [] =
this.check_shim(abi, ExternAbi::System { unwind: false }, link_name, args)?; this.check_shim(abi, sys_conv, link_name, args)?;
this.write_pointer( this.write_pointer(
this.machine.cmd_line.expect("machine must be initialized"), this.machine.cmd_line.expect("machine must be initialized"),
dest, dest,
@ -406,32 +413,32 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
"GetSystemTimeAsFileTime" | "GetSystemTimePreciseAsFileTime" => { "GetSystemTimeAsFileTime" | "GetSystemTimePreciseAsFileTime" => {
#[allow(non_snake_case)] #[allow(non_snake_case)]
let [LPFILETIME] = let [LPFILETIME] =
this.check_shim(abi, ExternAbi::System { unwind: false }, link_name, args)?; this.check_shim(abi, sys_conv, link_name, args)?;
this.GetSystemTimeAsFileTime(link_name.as_str(), LPFILETIME)?; this.GetSystemTimeAsFileTime(link_name.as_str(), LPFILETIME)?;
} }
"QueryPerformanceCounter" => { "QueryPerformanceCounter" => {
#[allow(non_snake_case)] #[allow(non_snake_case)]
let [lpPerformanceCount] = let [lpPerformanceCount] =
this.check_shim(abi, ExternAbi::System { unwind: false }, link_name, args)?; this.check_shim(abi, sys_conv, link_name, args)?;
let result = this.QueryPerformanceCounter(lpPerformanceCount)?; let result = this.QueryPerformanceCounter(lpPerformanceCount)?;
this.write_scalar(result, dest)?; this.write_scalar(result, dest)?;
} }
"QueryPerformanceFrequency" => { "QueryPerformanceFrequency" => {
#[allow(non_snake_case)] #[allow(non_snake_case)]
let [lpFrequency] = let [lpFrequency] =
this.check_shim(abi, ExternAbi::System { unwind: false }, link_name, args)?; this.check_shim(abi, sys_conv, link_name, args)?;
let result = this.QueryPerformanceFrequency(lpFrequency)?; let result = this.QueryPerformanceFrequency(lpFrequency)?;
this.write_scalar(result, dest)?; this.write_scalar(result, dest)?;
} }
"Sleep" => { "Sleep" => {
let [timeout] = let [timeout] =
this.check_shim(abi, ExternAbi::System { unwind: false }, link_name, args)?; this.check_shim(abi, sys_conv, link_name, args)?;
this.Sleep(timeout)?; this.Sleep(timeout)?;
} }
"CreateWaitableTimerExW" => { "CreateWaitableTimerExW" => {
let [attributes, name, flags, access] = let [attributes, name, flags, access] =
this.check_shim(abi, ExternAbi::System { unwind: false }, link_name, args)?; this.check_shim(abi, sys_conv, link_name, args)?;
this.read_pointer(attributes)?; this.read_pointer(attributes)?;
this.read_pointer(name)?; this.read_pointer(name)?;
this.read_scalar(flags)?.to_u32()?; this.read_scalar(flags)?.to_u32()?;
@ -445,30 +452,30 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
// Synchronization primitives // Synchronization primitives
"InitOnceBeginInitialize" => { "InitOnceBeginInitialize" => {
let [ptr, flags, pending, context] = let [ptr, flags, pending, context] =
this.check_shim(abi, ExternAbi::System { unwind: false }, link_name, args)?; this.check_shim(abi, sys_conv, link_name, args)?;
this.InitOnceBeginInitialize(ptr, flags, pending, context, dest)?; this.InitOnceBeginInitialize(ptr, flags, pending, context, dest)?;
} }
"InitOnceComplete" => { "InitOnceComplete" => {
let [ptr, flags, context] = let [ptr, flags, context] =
this.check_shim(abi, ExternAbi::System { unwind: false }, link_name, args)?; this.check_shim(abi, sys_conv, link_name, args)?;
let result = this.InitOnceComplete(ptr, flags, context)?; let result = this.InitOnceComplete(ptr, flags, context)?;
this.write_scalar(result, dest)?; this.write_scalar(result, dest)?;
} }
"WaitOnAddress" => { "WaitOnAddress" => {
let [ptr_op, compare_op, size_op, timeout_op] = let [ptr_op, compare_op, size_op, timeout_op] =
this.check_shim(abi, ExternAbi::System { unwind: false }, link_name, args)?; this.check_shim(abi, sys_conv, link_name, args)?;
this.WaitOnAddress(ptr_op, compare_op, size_op, timeout_op, dest)?; this.WaitOnAddress(ptr_op, compare_op, size_op, timeout_op, dest)?;
} }
"WakeByAddressSingle" => { "WakeByAddressSingle" => {
let [ptr_op] = let [ptr_op] =
this.check_shim(abi, ExternAbi::System { unwind: false }, link_name, args)?; this.check_shim(abi, sys_conv, link_name, args)?;
this.WakeByAddressSingle(ptr_op)?; this.WakeByAddressSingle(ptr_op)?;
} }
"WakeByAddressAll" => { "WakeByAddressAll" => {
let [ptr_op] = let [ptr_op] =
this.check_shim(abi, ExternAbi::System { unwind: false }, link_name, args)?; this.check_shim(abi, sys_conv, link_name, args)?;
this.WakeByAddressAll(ptr_op)?; this.WakeByAddressAll(ptr_op)?;
} }
@ -477,7 +484,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
"GetProcAddress" => { "GetProcAddress" => {
#[allow(non_snake_case)] #[allow(non_snake_case)]
let [hModule, lpProcName] = let [hModule, lpProcName] =
this.check_shim(abi, ExternAbi::System { unwind: false }, link_name, args)?; this.check_shim(abi, sys_conv, link_name, args)?;
this.read_target_isize(hModule)?; this.read_target_isize(hModule)?;
let name = this.read_c_str(this.read_pointer(lpProcName)?)?; let name = this.read_c_str(this.read_pointer(lpProcName)?)?;
if let Ok(name) = str::from_utf8(name) if let Ok(name) = str::from_utf8(name)
@ -493,7 +500,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
// Threading // Threading
"CreateThread" => { "CreateThread" => {
let [security, stacksize, start, arg, flags, thread] = let [security, stacksize, start, arg, flags, thread] =
this.check_shim(abi, ExternAbi::System { unwind: false }, link_name, args)?; this.check_shim(abi, sys_conv, link_name, args)?;
let thread_id = let thread_id =
this.CreateThread(security, stacksize, start, arg, flags, thread)?; this.CreateThread(security, stacksize, start, arg, flags, thread)?;
@ -502,14 +509,14 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
} }
"WaitForSingleObject" => { "WaitForSingleObject" => {
let [handle, timeout] = let [handle, timeout] =
this.check_shim(abi, ExternAbi::System { unwind: false }, link_name, args)?; this.check_shim(abi, sys_conv, link_name, args)?;
let ret = this.WaitForSingleObject(handle, timeout)?; let ret = this.WaitForSingleObject(handle, timeout)?;
this.write_scalar(ret, dest)?; this.write_scalar(ret, dest)?;
} }
"GetCurrentThread" => { "GetCurrentThread" => {
let [] = let [] =
this.check_shim(abi, ExternAbi::System { unwind: false }, link_name, args)?; this.check_shim(abi, sys_conv, link_name, args)?;
this.write_scalar( this.write_scalar(
Handle::Pseudo(PseudoHandle::CurrentThread).to_scalar(this), Handle::Pseudo(PseudoHandle::CurrentThread).to_scalar(this),
@ -518,7 +525,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
} }
"SetThreadDescription" => { "SetThreadDescription" => {
let [handle, name] = let [handle, name] =
this.check_shim(abi, ExternAbi::System { unwind: false }, link_name, args)?; this.check_shim(abi, sys_conv, link_name, args)?;
let handle = this.read_scalar(handle)?; let handle = this.read_scalar(handle)?;
let name = this.read_wide_str(this.read_pointer(name)?)?; let name = this.read_wide_str(this.read_pointer(name)?)?;
@ -543,7 +550,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
} }
"GetThreadDescription" => { "GetThreadDescription" => {
let [handle, name_ptr] = let [handle, name_ptr] =
this.check_shim(abi, ExternAbi::System { unwind: false }, link_name, args)?; this.check_shim(abi, sys_conv, link_name, args)?;
let handle = this.read_scalar(handle)?; let handle = this.read_scalar(handle)?;
let name_ptr = this.deref_pointer(name_ptr)?; // the pointer where we should store the ptr to the name let name_ptr = this.deref_pointer(name_ptr)?; // the pointer where we should store the ptr to the name
@ -575,7 +582,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
// Miscellaneous // Miscellaneous
"ExitProcess" => { "ExitProcess" => {
let [code] = let [code] =
this.check_shim(abi, ExternAbi::System { unwind: false }, link_name, args)?; this.check_shim(abi, sys_conv, link_name, args)?;
let code = this.read_scalar(code)?.to_u32()?; let code = this.read_scalar(code)?.to_u32()?;
throw_machine_stop!(TerminationInfo::Exit { code: code.into(), leak_check: false }); throw_machine_stop!(TerminationInfo::Exit { code: code.into(), leak_check: false });
} }
@ -583,7 +590,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
// used by getrandom 0.1 // used by getrandom 0.1
// This is really 'RtlGenRandom'. // This is really 'RtlGenRandom'.
let [ptr, len] = let [ptr, len] =
this.check_shim(abi, ExternAbi::System { unwind: false }, link_name, args)?; this.check_shim(abi, sys_conv, link_name, args)?;
let ptr = this.read_pointer(ptr)?; let ptr = this.read_pointer(ptr)?;
let len = this.read_scalar(len)?.to_u32()?; let len = this.read_scalar(len)?.to_u32()?;
this.gen_random(ptr, len.into())?; this.gen_random(ptr, len.into())?;
@ -592,7 +599,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
"ProcessPrng" => { "ProcessPrng" => {
// used by `std` // used by `std`
let [ptr, len] = let [ptr, len] =
this.check_shim(abi, ExternAbi::System { unwind: false }, link_name, args)?; this.check_shim(abi, sys_conv, link_name, args)?;
let ptr = this.read_pointer(ptr)?; let ptr = this.read_pointer(ptr)?;
let len = this.read_target_usize(len)?; let len = this.read_target_usize(len)?;
this.gen_random(ptr, len)?; this.gen_random(ptr, len)?;
@ -601,7 +608,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
"BCryptGenRandom" => { "BCryptGenRandom" => {
// used by getrandom 0.2 // used by getrandom 0.2
let [algorithm, ptr, len, flags] = let [algorithm, ptr, len, flags] =
this.check_shim(abi, ExternAbi::System { unwind: false }, link_name, args)?; this.check_shim(abi, sys_conv, link_name, args)?;
let algorithm = this.read_scalar(algorithm)?; let algorithm = this.read_scalar(algorithm)?;
let algorithm = algorithm.to_target_usize(this)?; let algorithm = algorithm.to_target_usize(this)?;
let ptr = this.read_pointer(ptr)?; let ptr = this.read_pointer(ptr)?;
@ -636,7 +643,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
"GetConsoleScreenBufferInfo" => { "GetConsoleScreenBufferInfo" => {
// `term` needs this, so we fake it. // `term` needs this, so we fake it.
let [console, buffer_info] = let [console, buffer_info] =
this.check_shim(abi, ExternAbi::System { unwind: false }, link_name, args)?; this.check_shim(abi, sys_conv, link_name, args)?;
this.read_target_isize(console)?; this.read_target_isize(console)?;
// FIXME: this should use deref_pointer_as, but CONSOLE_SCREEN_BUFFER_INFO is not in std // FIXME: this should use deref_pointer_as, but CONSOLE_SCREEN_BUFFER_INFO is not in std
this.deref_pointer(buffer_info)?; this.deref_pointer(buffer_info)?;
@ -646,7 +653,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
} }
"GetStdHandle" => { "GetStdHandle" => {
let [which] = let [which] =
this.check_shim(abi, ExternAbi::System { unwind: false }, link_name, args)?; this.check_shim(abi, sys_conv, link_name, args)?;
let which = this.read_scalar(which)?.to_i32()?; let which = this.read_scalar(which)?.to_i32()?;
// We just make this the identity function, so we know later in `NtWriteFile` which // We just make this the identity function, so we know later in `NtWriteFile` which
// one it is. This is very fake, but libtest needs it so we cannot make it a // one it is. This is very fake, but libtest needs it so we cannot make it a
@ -656,7 +663,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
} }
"CloseHandle" => { "CloseHandle" => {
let [handle] = let [handle] =
this.check_shim(abi, ExternAbi::System { unwind: false }, link_name, args)?; this.check_shim(abi, sys_conv, link_name, args)?;
let ret = this.CloseHandle(handle)?; let ret = this.CloseHandle(handle)?;
@ -664,7 +671,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
} }
"GetModuleFileNameW" => { "GetModuleFileNameW" => {
let [handle, filename, size] = let [handle, filename, size] =
this.check_shim(abi, ExternAbi::System { unwind: false }, link_name, args)?; this.check_shim(abi, sys_conv, link_name, args)?;
this.check_no_isolation("`GetModuleFileNameW`")?; this.check_no_isolation("`GetModuleFileNameW`")?;
let handle = this.read_target_usize(handle)?; let handle = this.read_target_usize(handle)?;
@ -698,7 +705,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
} }
"FormatMessageW" => { "FormatMessageW" => {
let [flags, module, message_id, language_id, buffer, size, arguments] = let [flags, module, message_id, language_id, buffer, size, arguments] =
this.check_shim(abi, ExternAbi::System { unwind: false }, link_name, args)?; this.check_shim(abi, sys_conv, link_name, args)?;
let flags = this.read_scalar(flags)?.to_u32()?; let flags = this.read_scalar(flags)?.to_u32()?;
let _module = this.read_pointer(module)?; // seems to contain a module name let _module = this.read_pointer(module)?; // seems to contain a module name
@ -734,7 +741,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
// These shims are enabled only when the caller is in the standard library. // These shims are enabled only when the caller is in the standard library.
"GetProcessHeap" if this.frame_in_std() => { "GetProcessHeap" if this.frame_in_std() => {
let [] = let [] =
this.check_shim(abi, ExternAbi::System { unwind: false }, link_name, args)?; this.check_shim(abi, sys_conv, link_name, args)?;
// Just fake a HANDLE // Just fake a HANDLE
// It's fine to not use the Handle type here because its a stub // It's fine to not use the Handle type here because its a stub
this.write_int(1, dest)?; this.write_int(1, dest)?;
@ -742,20 +749,20 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
"GetModuleHandleA" if this.frame_in_std() => { "GetModuleHandleA" if this.frame_in_std() => {
#[allow(non_snake_case)] #[allow(non_snake_case)]
let [_lpModuleName] = let [_lpModuleName] =
this.check_shim(abi, ExternAbi::System { unwind: false }, link_name, args)?; this.check_shim(abi, sys_conv, link_name, args)?;
// We need to return something non-null here to make `compat_fn!` work. // We need to return something non-null here to make `compat_fn!` work.
this.write_int(1, dest)?; this.write_int(1, dest)?;
} }
"SetConsoleTextAttribute" if this.frame_in_std() => { "SetConsoleTextAttribute" if this.frame_in_std() => {
#[allow(non_snake_case)] #[allow(non_snake_case)]
let [_hConsoleOutput, _wAttribute] = let [_hConsoleOutput, _wAttribute] =
this.check_shim(abi, ExternAbi::System { unwind: false }, link_name, args)?; this.check_shim(abi, sys_conv, link_name, args)?;
// Pretend these does not exist / nothing happened, by returning zero. // Pretend these does not exist / nothing happened, by returning zero.
this.write_null(dest)?; this.write_null(dest)?;
} }
"GetConsoleMode" if this.frame_in_std() => { "GetConsoleMode" if this.frame_in_std() => {
let [console, mode] = let [console, mode] =
this.check_shim(abi, ExternAbi::System { unwind: false }, link_name, args)?; this.check_shim(abi, sys_conv, link_name, args)?;
this.read_target_isize(console)?; this.read_target_isize(console)?;
this.deref_pointer(mode)?; this.deref_pointer(mode)?;
// Indicate an error. // Indicate an error.
@ -764,28 +771,28 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
"GetFileType" if this.frame_in_std() => { "GetFileType" if this.frame_in_std() => {
#[allow(non_snake_case)] #[allow(non_snake_case)]
let [_hFile] = let [_hFile] =
this.check_shim(abi, ExternAbi::System { unwind: false }, link_name, args)?; this.check_shim(abi, sys_conv, link_name, args)?;
// Return unknown file type. // Return unknown file type.
this.write_null(dest)?; this.write_null(dest)?;
} }
"AddVectoredExceptionHandler" if this.frame_in_std() => { "AddVectoredExceptionHandler" if this.frame_in_std() => {
#[allow(non_snake_case)] #[allow(non_snake_case)]
let [_First, _Handler] = let [_First, _Handler] =
this.check_shim(abi, ExternAbi::System { unwind: false }, link_name, args)?; this.check_shim(abi, sys_conv, link_name, args)?;
// Any non zero value works for the stdlib. This is just used for stack overflows anyway. // Any non zero value works for the stdlib. This is just used for stack overflows anyway.
this.write_int(1, dest)?; this.write_int(1, dest)?;
} }
"SetThreadStackGuarantee" if this.frame_in_std() => { "SetThreadStackGuarantee" if this.frame_in_std() => {
#[allow(non_snake_case)] #[allow(non_snake_case)]
let [_StackSizeInBytes] = let [_StackSizeInBytes] =
this.check_shim(abi, ExternAbi::System { unwind: false }, link_name, args)?; this.check_shim(abi, sys_conv, link_name, args)?;
// Any non zero value works for the stdlib. This is just used for stack overflows anyway. // Any non zero value works for the stdlib. This is just used for stack overflows anyway.
this.write_int(1, dest)?; this.write_int(1, dest)?;
} }
// this is only callable from std because we know that std ignores the return value // this is only callable from std because we know that std ignores the return value
"SwitchToThread" if this.frame_in_std() => { "SwitchToThread" if this.frame_in_std() => {
let [] = let [] =
this.check_shim(abi, ExternAbi::System { unwind: false }, link_name, args)?; this.check_shim(abi, sys_conv, link_name, args)?;
this.yield_active_thread(); this.yield_active_thread();
@ -805,7 +812,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
} }
// This function looks and behaves excatly like miri_start_unwind. // This function looks and behaves excatly like miri_start_unwind.
let [payload] = let [payload] =
this.check_shim(abi, ExternAbi::C { unwind: true }, link_name, args)?; this.check_shim(abi, Conv::C, link_name, args)?;
this.handle_miri_start_unwind(payload)?; this.handle_miri_start_unwind(payload)?;
return interp_ok(EmulateItemResult::NeedsUnwind); return interp_ok(EmulateItemResult::NeedsUnwind);
} }

View file

@ -1,7 +1,7 @@
use rustc_abi::ExternAbi;
use rustc_middle::ty::Ty; use rustc_middle::ty::Ty;
use rustc_middle::ty::layout::LayoutOf as _; use rustc_middle::ty::layout::LayoutOf as _;
use rustc_span::Symbol; use rustc_span::Symbol;
use rustc_target::callconv::{Conv, FnAbi};
use crate::*; use crate::*;
@ -10,7 +10,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
fn emulate_x86_aesni_intrinsic( fn emulate_x86_aesni_intrinsic(
&mut self, &mut self,
link_name: Symbol, link_name: Symbol,
abi: ExternAbi, abi: &FnAbi<'tcx, Ty<'tcx>>,
args: &[OpTy<'tcx>], args: &[OpTy<'tcx>],
dest: &MPlaceTy<'tcx>, dest: &MPlaceTy<'tcx>,
) -> InterpResult<'tcx, EmulateItemResult> { ) -> InterpResult<'tcx, EmulateItemResult> {
@ -27,8 +27,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_aesdec_si128 // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_aesdec_si128
"aesdec" | "aesdec.256" | "aesdec.512" => { "aesdec" | "aesdec.256" | "aesdec.512" => {
let [state, key] = let [state, key] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C, link_name, args)?;
aes_round(this, state, key, dest, |state, key| { aes_round(this, state, key, dest, |state, key| {
let key = aes::Block::from(key.to_le_bytes()); let key = aes::Block::from(key.to_le_bytes());
let mut state = aes::Block::from(state.to_le_bytes()); let mut state = aes::Block::from(state.to_le_bytes());
@ -45,7 +44,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_aesdeclast_si128 // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_aesdeclast_si128
"aesdeclast" | "aesdeclast.256" | "aesdeclast.512" => { "aesdeclast" | "aesdeclast.256" | "aesdeclast.512" => {
let [state, key] = let [state, key] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C, link_name, args)?;
aes_round(this, state, key, dest, |state, key| { aes_round(this, state, key, dest, |state, key| {
let mut state = aes::Block::from(state.to_le_bytes()); let mut state = aes::Block::from(state.to_le_bytes());
@ -70,8 +69,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_aesenc_si128 // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_aesenc_si128
"aesenc" | "aesenc.256" | "aesenc.512" => { "aesenc" | "aesenc.256" | "aesenc.512" => {
let [state, key] = let [state, key] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C, link_name, args)?;
aes_round(this, state, key, dest, |state, key| { aes_round(this, state, key, dest, |state, key| {
let key = aes::Block::from(key.to_le_bytes()); let key = aes::Block::from(key.to_le_bytes());
let mut state = aes::Block::from(state.to_le_bytes()); let mut state = aes::Block::from(state.to_le_bytes());
@ -88,8 +86,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_aesenclast_si128 // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_aesenclast_si128
"aesenclast" | "aesenclast.256" | "aesenclast.512" => { "aesenclast" | "aesenclast.256" | "aesenclast.512" => {
let [state, key] = let [state, key] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C, link_name, args)?;
aes_round(this, state, key, dest, |state, key| { aes_round(this, state, key, dest, |state, key| {
let mut state = aes::Block::from(state.to_le_bytes()); let mut state = aes::Block::from(state.to_le_bytes());
// `aes::hazmat::cipher_round` does the following operations: // `aes::hazmat::cipher_round` does the following operations:
@ -109,8 +106,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
// Used to implement the _mm_aesimc_si128 function. // Used to implement the _mm_aesimc_si128 function.
// Performs the AES InvMixColumns operation on `op` // Performs the AES InvMixColumns operation on `op`
"aesimc" => { "aesimc" => {
let [op] = this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; let [op] = this.check_shim(abi, Conv::C, link_name, args)?;
// Transmute to `u128` // Transmute to `u128`
let op = op.transmute(this.machine.layouts.u128, this)?; let op = op.transmute(this.machine.layouts.u128, this)?;
let dest = dest.transmute(this.machine.layouts.u128, this)?; let dest = dest.transmute(this.machine.layouts.u128, this)?;

View file

@ -1,9 +1,9 @@
use rustc_abi::ExternAbi;
use rustc_apfloat::ieee::{Double, Single}; use rustc_apfloat::ieee::{Double, Single};
use rustc_middle::mir; use rustc_middle::mir;
use rustc_middle::ty::Ty; use rustc_middle::ty::Ty;
use rustc_middle::ty::layout::LayoutOf as _; use rustc_middle::ty::layout::LayoutOf as _;
use rustc_span::Symbol; use rustc_span::Symbol;
use rustc_target::callconv::{Conv, FnAbi};
use super::{ use super::{
FloatBinOp, FloatUnaryOp, bin_op_simd_float_all, conditional_dot_product, convert_float_to_int, FloatBinOp, FloatUnaryOp, bin_op_simd_float_all, conditional_dot_product, convert_float_to_int,
@ -17,7 +17,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
fn emulate_x86_avx_intrinsic( fn emulate_x86_avx_intrinsic(
&mut self, &mut self,
link_name: Symbol, link_name: Symbol,
abi: ExternAbi, abi: &FnAbi<'tcx, Ty<'tcx>>,
args: &[OpTy<'tcx>], args: &[OpTy<'tcx>],
dest: &MPlaceTy<'tcx>, dest: &MPlaceTy<'tcx>,
) -> InterpResult<'tcx, EmulateItemResult> { ) -> InterpResult<'tcx, EmulateItemResult> {
@ -34,7 +34,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
// semantics. // semantics.
"min.ps.256" | "max.ps.256" => { "min.ps.256" | "max.ps.256" => {
let [left, right] = let [left, right] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C, link_name, args)?;
let which = match unprefixed_name { let which = match unprefixed_name {
"min.ps.256" => FloatBinOp::Min, "min.ps.256" => FloatBinOp::Min,
@ -47,7 +47,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
// Used to implement _mm256_min_pd and _mm256_max_pd functions. // Used to implement _mm256_min_pd and _mm256_max_pd functions.
"min.pd.256" | "max.pd.256" => { "min.pd.256" | "max.pd.256" => {
let [left, right] = let [left, right] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C, link_name, args)?;
let which = match unprefixed_name { let which = match unprefixed_name {
"min.pd.256" => FloatBinOp::Min, "min.pd.256" => FloatBinOp::Min,
@ -61,7 +61,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
// Rounds the elements of `op` according to `rounding`. // Rounds the elements of `op` according to `rounding`.
"round.ps.256" => { "round.ps.256" => {
let [op, rounding] = let [op, rounding] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C, link_name, args)?;
round_all::<rustc_apfloat::ieee::Single>(this, op, rounding, dest)?; round_all::<rustc_apfloat::ieee::Single>(this, op, rounding, dest)?;
} }
@ -69,14 +69,14 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
// Rounds the elements of `op` according to `rounding`. // Rounds the elements of `op` according to `rounding`.
"round.pd.256" => { "round.pd.256" => {
let [op, rounding] = let [op, rounding] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C, link_name, args)?;
round_all::<rustc_apfloat::ieee::Double>(this, op, rounding, dest)?; round_all::<rustc_apfloat::ieee::Double>(this, op, rounding, dest)?;
} }
// Used to implement _mm256_{rcp,rsqrt}_ps functions. // Used to implement _mm256_{rcp,rsqrt}_ps functions.
// Performs the operations on all components of `op`. // Performs the operations on all components of `op`.
"rcp.ps.256" | "rsqrt.ps.256" => { "rcp.ps.256" | "rsqrt.ps.256" => {
let [op] = this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; let [op] = this.check_shim(abi, Conv::C, link_name, args)?;
let which = match unprefixed_name { let which = match unprefixed_name {
"rcp.ps.256" => FloatUnaryOp::Rcp, "rcp.ps.256" => FloatUnaryOp::Rcp,
@ -89,7 +89,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
// Used to implement the _mm256_dp_ps function. // Used to implement the _mm256_dp_ps function.
"dp.ps.256" => { "dp.ps.256" => {
let [left, right, imm] = let [left, right, imm] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C, link_name, args)?;
conditional_dot_product(this, left, right, imm, dest)?; conditional_dot_product(this, left, right, imm, dest)?;
} }
@ -98,7 +98,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
// in `left` and `right`. // in `left` and `right`.
"hadd.ps.256" | "hadd.pd.256" | "hsub.ps.256" | "hsub.pd.256" => { "hadd.ps.256" | "hadd.pd.256" | "hsub.ps.256" | "hsub.pd.256" => {
let [left, right] = let [left, right] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C, link_name, args)?;
let which = match unprefixed_name { let which = match unprefixed_name {
"hadd.ps.256" | "hadd.pd.256" => mir::BinOp::Add, "hadd.ps.256" | "hadd.pd.256" => mir::BinOp::Add,
@ -114,7 +114,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
// if true. // if true.
"cmp.ps.256" => { "cmp.ps.256" => {
let [left, right, imm] = let [left, right, imm] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C, link_name, args)?;
let which = let which =
FloatBinOp::cmp_from_imm(this, this.read_scalar(imm)?.to_i8()?, link_name)?; FloatBinOp::cmp_from_imm(this, this.read_scalar(imm)?.to_i8()?, link_name)?;
@ -127,7 +127,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
// if true. // if true.
"cmp.pd.256" => { "cmp.pd.256" => {
let [left, right, imm] = let [left, right, imm] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C, link_name, args)?;
let which = let which =
FloatBinOp::cmp_from_imm(this, this.read_scalar(imm)?.to_i8()?, link_name)?; FloatBinOp::cmp_from_imm(this, this.read_scalar(imm)?.to_i8()?, link_name)?;
@ -138,7 +138,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
// and _mm256_cvttpd_epi32 functions. // and _mm256_cvttpd_epi32 functions.
// Converts packed f32/f64 to packed i32. // Converts packed f32/f64 to packed i32.
"cvt.ps2dq.256" | "cvtt.ps2dq.256" | "cvt.pd2dq.256" | "cvtt.pd2dq.256" => { "cvt.ps2dq.256" | "cvtt.ps2dq.256" | "cvt.pd2dq.256" | "cvtt.pd2dq.256" => {
let [op] = this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; let [op] = this.check_shim(abi, Conv::C, link_name, args)?;
let rnd = match unprefixed_name { let rnd = match unprefixed_name {
// "current SSE rounding mode", assume nearest // "current SSE rounding mode", assume nearest
@ -157,7 +157,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
// `control` determines which element of the current `data` array is written. // `control` determines which element of the current `data` array is written.
"vpermilvar.ps" | "vpermilvar.ps.256" => { "vpermilvar.ps" | "vpermilvar.ps.256" => {
let [data, control] = let [data, control] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C, link_name, args)?;
let (data, data_len) = this.project_to_simd(data)?; let (data, data_len) = this.project_to_simd(data)?;
let (control, control_len) = this.project_to_simd(control)?; let (control, control_len) = this.project_to_simd(control)?;
@ -191,7 +191,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
// written. // written.
"vpermilvar.pd" | "vpermilvar.pd.256" => { "vpermilvar.pd" | "vpermilvar.pd.256" => {
let [data, control] = let [data, control] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C, link_name, args)?;
let (data, data_len) = this.project_to_simd(data)?; let (data, data_len) = this.project_to_simd(data)?;
let (control, control_len) = this.project_to_simd(control)?; let (control, control_len) = this.project_to_simd(control)?;
@ -224,7 +224,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
// zero, according to `imm`. // zero, according to `imm`.
"vperm2f128.ps.256" | "vperm2f128.pd.256" | "vperm2f128.si.256" => { "vperm2f128.ps.256" | "vperm2f128.pd.256" | "vperm2f128.si.256" => {
let [left, right, imm] = let [left, right, imm] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C, link_name, args)?;
assert_eq!(dest.layout, left.layout); assert_eq!(dest.layout, left.layout);
assert_eq!(dest.layout, right.layout); assert_eq!(dest.layout, right.layout);
@ -268,7 +268,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
// loaded. // loaded.
"maskload.ps" | "maskload.pd" | "maskload.ps.256" | "maskload.pd.256" => { "maskload.ps" | "maskload.pd" | "maskload.ps.256" | "maskload.pd.256" => {
let [ptr, mask] = let [ptr, mask] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C, link_name, args)?;
mask_load(this, ptr, mask, dest)?; mask_load(this, ptr, mask, dest)?;
} }
@ -279,7 +279,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
// Unlike SSE2's _mm_maskmoveu_si128, these are not non-temporal stores. // Unlike SSE2's _mm_maskmoveu_si128, these are not non-temporal stores.
"maskstore.ps" | "maskstore.pd" | "maskstore.ps.256" | "maskstore.pd.256" => { "maskstore.ps" | "maskstore.pd" | "maskstore.ps.256" | "maskstore.pd.256" => {
let [ptr, mask, value] = let [ptr, mask, value] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C, link_name, args)?;
mask_store(this, ptr, mask, value)?; mask_store(this, ptr, mask, value)?;
} }
@ -290,7 +290,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
// unaligned read. // unaligned read.
"ldu.dq.256" => { "ldu.dq.256" => {
let [src_ptr] = let [src_ptr] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C, link_name, args)?;
let src_ptr = this.read_pointer(src_ptr)?; let src_ptr = this.read_pointer(src_ptr)?;
let dest = dest.force_mplace(this)?; let dest = dest.force_mplace(this)?;
@ -303,7 +303,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
// `op & mask != 0 && op & mask != mask` // `op & mask != 0 && op & mask != mask`
"ptestz.256" | "ptestc.256" | "ptestnzc.256" => { "ptestz.256" | "ptestc.256" | "ptestnzc.256" => {
let [op, mask] = let [op, mask] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C, link_name, args)?;
let (all_zero, masked_set) = test_bits_masked(this, op, mask)?; let (all_zero, masked_set) = test_bits_masked(this, op, mask)?;
let res = match unprefixed_name { let res = match unprefixed_name {
@ -327,7 +327,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
| "vtestnzc.pd" | "vtestz.ps.256" | "vtestc.ps.256" | "vtestnzc.ps.256" | "vtestnzc.pd" | "vtestz.ps.256" | "vtestc.ps.256" | "vtestnzc.ps.256"
| "vtestz.ps" | "vtestc.ps" | "vtestnzc.ps" => { | "vtestz.ps" | "vtestc.ps" | "vtestnzc.ps" => {
let [op, mask] = let [op, mask] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C, link_name, args)?;
let (direct, negated) = test_high_bits_masked(this, op, mask)?; let (direct, negated) = test_high_bits_masked(this, op, mask)?;
let res = match unprefixed_name { let res = match unprefixed_name {
@ -349,7 +349,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
// compiler, making these functions no-ops. // compiler, making these functions no-ops.
// The only thing that needs to be ensured is the correct calling convention. // The only thing that needs to be ensured is the correct calling convention.
let [] = this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; let [] = this.check_shim(abi, Conv::C, link_name, args)?;
} }
_ => return interp_ok(EmulateItemResult::NotSupported), _ => return interp_ok(EmulateItemResult::NotSupported),
} }

View file

@ -1,8 +1,8 @@
use rustc_abi::ExternAbi;
use rustc_middle::mir; use rustc_middle::mir;
use rustc_middle::ty::Ty; use rustc_middle::ty::Ty;
use rustc_middle::ty::layout::LayoutOf as _; use rustc_middle::ty::layout::LayoutOf as _;
use rustc_span::Symbol; use rustc_span::Symbol;
use rustc_target::callconv::{Conv, FnAbi};
use super::{ use super::{
ShiftOp, horizontal_bin_op, int_abs, mask_load, mask_store, mpsadbw, packssdw, packsswb, ShiftOp, horizontal_bin_op, int_abs, mask_load, mask_store, mpsadbw, packssdw, packsswb,
@ -15,7 +15,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
fn emulate_x86_avx2_intrinsic( fn emulate_x86_avx2_intrinsic(
&mut self, &mut self,
link_name: Symbol, link_name: Symbol,
abi: ExternAbi, abi: &FnAbi<'tcx, Ty<'tcx>>,
args: &[OpTy<'tcx>], args: &[OpTy<'tcx>],
dest: &MPlaceTy<'tcx>, dest: &MPlaceTy<'tcx>,
) -> InterpResult<'tcx, EmulateItemResult> { ) -> InterpResult<'tcx, EmulateItemResult> {
@ -28,7 +28,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
// Used to implement the _mm256_abs_epi{8,16,32} functions. // Used to implement the _mm256_abs_epi{8,16,32} functions.
// Calculates the absolute value of packed 8/16/32-bit integers. // Calculates the absolute value of packed 8/16/32-bit integers.
"pabs.b" | "pabs.w" | "pabs.d" => { "pabs.b" | "pabs.w" | "pabs.d" => {
let [op] = this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; let [op] = this.check_shim(abi, Conv::C, link_name, args)?;
int_abs(this, op, dest)?; int_abs(this, op, dest)?;
} }
@ -37,7 +37,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
// integer values in `left` and `right`. // integer values in `left` and `right`.
"phadd.w" | "phadd.sw" | "phadd.d" | "phsub.w" | "phsub.sw" | "phsub.d" => { "phadd.w" | "phadd.sw" | "phadd.d" | "phsub.w" | "phsub.sw" | "phsub.d" => {
let [left, right] = let [left, right] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C, link_name, args)?;
let (which, saturating) = match unprefixed_name { let (which, saturating) = match unprefixed_name {
"phadd.w" | "phadd.d" => (mir::BinOp::Add, false), "phadd.w" | "phadd.d" => (mir::BinOp::Add, false),
@ -58,7 +58,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
| "gather.d.pd.256" | "gather.q.pd" | "gather.q.pd.256" | "gather.d.ps" | "gather.d.pd.256" | "gather.q.pd" | "gather.q.pd.256" | "gather.d.ps"
| "gather.d.ps.256" | "gather.q.ps" | "gather.q.ps.256" => { | "gather.d.ps.256" | "gather.q.ps" | "gather.q.ps.256" => {
let [src, slice, offsets, mask, scale] = let [src, slice, offsets, mask, scale] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C, link_name, args)?;
assert_eq!(dest.layout, src.layout); assert_eq!(dest.layout, src.layout);
@ -116,7 +116,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
// intermediate 32-bit integers, and pack the results in `dest`. // intermediate 32-bit integers, and pack the results in `dest`.
"pmadd.wd" => { "pmadd.wd" => {
let [left, right] = let [left, right] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C, link_name, args)?;
let (left, left_len) = this.project_to_simd(left)?; let (left, left_len) = this.project_to_simd(left)?;
let (right, right_len) = this.project_to_simd(right)?; let (right, right_len) = this.project_to_simd(right)?;
@ -153,7 +153,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
// produces the output at index `i`. // produces the output at index `i`.
"pmadd.ub.sw" => { "pmadd.ub.sw" => {
let [left, right] = let [left, right] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C, link_name, args)?;
let (left, left_len) = this.project_to_simd(left)?; let (left, left_len) = this.project_to_simd(left)?;
let (right, right_len) = this.project_to_simd(right)?; let (right, right_len) = this.project_to_simd(right)?;
@ -188,7 +188,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
// loaded. // loaded.
"maskload.d" | "maskload.q" | "maskload.d.256" | "maskload.q.256" => { "maskload.d" | "maskload.q" | "maskload.d.256" | "maskload.q.256" => {
let [ptr, mask] = let [ptr, mask] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C, link_name, args)?;
mask_load(this, ptr, mask, dest)?; mask_load(this, ptr, mask, dest)?;
} }
@ -199,7 +199,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
// Unlike SSE2's _mm_maskmoveu_si128, these are not non-temporal stores. // Unlike SSE2's _mm_maskmoveu_si128, these are not non-temporal stores.
"maskstore.d" | "maskstore.q" | "maskstore.d.256" | "maskstore.q.256" => { "maskstore.d" | "maskstore.q" | "maskstore.d.256" | "maskstore.q.256" => {
let [ptr, mask, value] = let [ptr, mask, value] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C, link_name, args)?;
mask_store(this, ptr, mask, value)?; mask_store(this, ptr, mask, value)?;
} }
@ -211,7 +211,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm256_mpsadbw_epu8 // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm256_mpsadbw_epu8
"mpsadbw" => { "mpsadbw" => {
let [left, right, imm] = let [left, right, imm] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C, link_name, args)?;
mpsadbw(this, left, right, imm, dest)?; mpsadbw(this, left, right, imm, dest)?;
} }
@ -223,7 +223,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm256_mulhrs_epi16 // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm256_mulhrs_epi16
"pmul.hr.sw" => { "pmul.hr.sw" => {
let [left, right] = let [left, right] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C, link_name, args)?;
pmulhrsw(this, left, right, dest)?; pmulhrsw(this, left, right, dest)?;
} }
@ -232,7 +232,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
// vector with signed saturation. // vector with signed saturation.
"packsswb" => { "packsswb" => {
let [left, right] = let [left, right] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C, link_name, args)?;
packsswb(this, left, right, dest)?; packsswb(this, left, right, dest)?;
} }
@ -241,7 +241,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
// vector with signed saturation. // vector with signed saturation.
"packssdw" => { "packssdw" => {
let [left, right] = let [left, right] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C, link_name, args)?;
packssdw(this, left, right, dest)?; packssdw(this, left, right, dest)?;
} }
@ -250,7 +250,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
// unsigned integer vector with saturation. // unsigned integer vector with saturation.
"packuswb" => { "packuswb" => {
let [left, right] = let [left, right] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C, link_name, args)?;
packuswb(this, left, right, dest)?; packuswb(this, left, right, dest)?;
} }
@ -259,7 +259,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
// the result to a 16-bit unsigned integer vector with saturation. // the result to a 16-bit unsigned integer vector with saturation.
"packusdw" => { "packusdw" => {
let [left, right] = let [left, right] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C, link_name, args)?;
packusdw(this, left, right, dest)?; packusdw(this, left, right, dest)?;
} }
@ -269,7 +269,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
// as indices. // as indices.
"permd" | "permps" => { "permd" | "permps" => {
let [left, right] = let [left, right] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C, link_name, args)?;
let (left, left_len) = this.project_to_simd(left)?; let (left, left_len) = this.project_to_simd(left)?;
let (right, right_len) = this.project_to_simd(right)?; let (right, right_len) = this.project_to_simd(right)?;
@ -290,7 +290,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
// Shuffles 128-bit blocks of `a` and `b` using `imm` as pattern. // Shuffles 128-bit blocks of `a` and `b` using `imm` as pattern.
"vperm2i128" => { "vperm2i128" => {
let [left, right, imm] = let [left, right, imm] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C, link_name, args)?;
assert_eq!(left.layout.size.bits(), 256); assert_eq!(left.layout.size.bits(), 256);
assert_eq!(right.layout.size.bits(), 256); assert_eq!(right.layout.size.bits(), 256);
@ -328,7 +328,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm256_sad_epu8 // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm256_sad_epu8
"psad.bw" => { "psad.bw" => {
let [left, right] = let [left, right] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C, link_name, args)?;
let (left, left_len) = this.project_to_simd(left)?; let (left, left_len) = this.project_to_simd(left)?;
let (right, right_len) = this.project_to_simd(right)?; let (right, right_len) = this.project_to_simd(right)?;
@ -361,7 +361,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
// Each 128-bit block is shuffled independently. // Each 128-bit block is shuffled independently.
"pshuf.b" => { "pshuf.b" => {
let [left, right] = let [left, right] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C, link_name, args)?;
let (left, left_len) = this.project_to_simd(left)?; let (left, left_len) = this.project_to_simd(left)?;
let (right, right_len) = this.project_to_simd(right)?; let (right, right_len) = this.project_to_simd(right)?;
@ -393,7 +393,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
// Basically, we multiply `left` with `right.signum()`. // Basically, we multiply `left` with `right.signum()`.
"psign.b" | "psign.w" | "psign.d" => { "psign.b" | "psign.w" | "psign.d" => {
let [left, right] = let [left, right] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C, link_name, args)?;
psign(this, left, right, dest)?; psign(this, left, right, dest)?;
} }
@ -408,7 +408,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
"psll.w" | "psrl.w" | "psra.w" | "psll.d" | "psrl.d" | "psra.d" | "psll.q" "psll.w" | "psrl.w" | "psra.w" | "psll.d" | "psrl.d" | "psra.d" | "psll.q"
| "psrl.q" => { | "psrl.q" => {
let [left, right] = let [left, right] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C, link_name, args)?;
let which = match unprefixed_name { let which = match unprefixed_name {
"psll.w" | "psll.d" | "psll.q" => ShiftOp::Left, "psll.w" | "psll.d" | "psll.q" => ShiftOp::Left,
@ -424,7 +424,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
"psllv.d" | "psllv.d.256" | "psllv.q" | "psllv.q.256" | "psrlv.d" | "psrlv.d.256" "psllv.d" | "psllv.d.256" | "psllv.q" | "psllv.q.256" | "psrlv.d" | "psrlv.d.256"
| "psrlv.q" | "psrlv.q.256" | "psrav.d" | "psrav.d.256" => { | "psrlv.q" | "psrlv.q.256" | "psrav.d" | "psrav.d.256" => {
let [left, right] = let [left, right] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C, link_name, args)?;
let which = match unprefixed_name { let which = match unprefixed_name {
"psllv.d" | "psllv.d.256" | "psllv.q" | "psllv.q.256" => ShiftOp::Left, "psllv.d" | "psllv.d.256" | "psllv.q" | "psllv.q.256" => ShiftOp::Left,

View file

@ -1,5 +1,6 @@
use rustc_abi::ExternAbi;
use rustc_span::Symbol; use rustc_span::Symbol;
use rustc_middle::ty::Ty;
use rustc_target::callconv::{Conv, FnAbi};
use crate::*; use crate::*;
@ -8,7 +9,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
fn emulate_x86_bmi_intrinsic( fn emulate_x86_bmi_intrinsic(
&mut self, &mut self,
link_name: Symbol, link_name: Symbol,
abi: ExternAbi, abi: &FnAbi<'tcx, Ty<'tcx>>,
args: &[OpTy<'tcx>], args: &[OpTy<'tcx>],
dest: &MPlaceTy<'tcx>, dest: &MPlaceTy<'tcx>,
) -> InterpResult<'tcx, EmulateItemResult> { ) -> InterpResult<'tcx, EmulateItemResult> {
@ -34,7 +35,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
} }
let [left, right] = let [left, right] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C, link_name, args)?;
let left = this.read_scalar(left)?; let left = this.read_scalar(left)?;
let right = this.read_scalar(right)?; let right = this.read_scalar(right)?;

View file

@ -1,5 +1,6 @@
use rustc_abi::ExternAbi;
use rustc_span::Symbol; use rustc_span::Symbol;
use rustc_middle::ty::Ty;
use rustc_target::callconv::{Conv, FnAbi};
use crate::*; use crate::*;
@ -8,7 +9,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
fn emulate_x86_gfni_intrinsic( fn emulate_x86_gfni_intrinsic(
&mut self, &mut self,
link_name: Symbol, link_name: Symbol,
abi: ExternAbi, abi: &FnAbi<'tcx, Ty<'tcx>>,
args: &[OpTy<'tcx>], args: &[OpTy<'tcx>],
dest: &MPlaceTy<'tcx>, dest: &MPlaceTy<'tcx>,
) -> InterpResult<'tcx, EmulateItemResult> { ) -> InterpResult<'tcx, EmulateItemResult> {
@ -30,7 +31,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=gf2p8affine_ // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=gf2p8affine_
"vgf2p8affineqb.128" | "vgf2p8affineqb.256" | "vgf2p8affineqb.512" => { "vgf2p8affineqb.128" | "vgf2p8affineqb.256" | "vgf2p8affineqb.512" => {
let [left, right, imm8] = let [left, right, imm8] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C, link_name, args)?;
affine_transform(this, left, right, imm8, dest, /* inverse */ false)?; affine_transform(this, left, right, imm8, dest, /* inverse */ false)?;
} }
// Used to implement the `_mm{, 256, 512}_gf2p8affineinv_epi64_epi8` functions. // Used to implement the `_mm{, 256, 512}_gf2p8affineinv_epi64_epi8` functions.
@ -38,7 +39,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=gf2p8affineinv // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=gf2p8affineinv
"vgf2p8affineinvqb.128" | "vgf2p8affineinvqb.256" | "vgf2p8affineinvqb.512" => { "vgf2p8affineinvqb.128" | "vgf2p8affineinvqb.256" | "vgf2p8affineinvqb.512" => {
let [left, right, imm8] = let [left, right, imm8] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C, link_name, args)?;
affine_transform(this, left, right, imm8, dest, /* inverse */ true)?; affine_transform(this, left, right, imm8, dest, /* inverse */ true)?;
} }
// Used to implement the `_mm{, 256, 512}_gf2p8mul_epi8` functions. // Used to implement the `_mm{, 256, 512}_gf2p8mul_epi8` functions.
@ -48,8 +49,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=gf2p8mul // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=gf2p8mul
"vgf2p8mulb.128" | "vgf2p8mulb.256" | "vgf2p8mulb.512" => { "vgf2p8mulb.128" | "vgf2p8mulb.256" | "vgf2p8mulb.512" => {
let [left, right] = let [left, right] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C, link_name, args)?;
let (left, left_len) = this.project_to_simd(left)?; let (left, left_len) = this.project_to_simd(left)?;
let (right, right_len) = this.project_to_simd(right)?; let (right, right_len) = this.project_to_simd(right)?;
let (dest, dest_len) = this.project_to_simd(dest)?; let (dest, dest_len) = this.project_to_simd(dest)?;

View file

@ -1,10 +1,11 @@
use rustc_abi::{ExternAbi, Size}; use rustc_abi::Size;
use rustc_apfloat::Float; use rustc_apfloat::Float;
use rustc_apfloat::ieee::Single; use rustc_apfloat::ieee::Single;
use rustc_middle::ty::Ty; use rustc_middle::ty::Ty;
use rustc_middle::ty::layout::LayoutOf as _; use rustc_middle::ty::layout::LayoutOf as _;
use rustc_middle::{mir, ty}; use rustc_middle::{mir, ty};
use rustc_span::Symbol; use rustc_span::Symbol;
use rustc_target::callconv::{Conv, FnAbi};
use self::helpers::bool_to_simd_element; use self::helpers::bool_to_simd_element;
use crate::*; use crate::*;
@ -27,7 +28,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
fn emulate_x86_intrinsic( fn emulate_x86_intrinsic(
&mut self, &mut self,
link_name: Symbol, link_name: Symbol,
abi: ExternAbi, abi: &FnAbi<'tcx, Ty<'tcx>>,
args: &[OpTy<'tcx>], args: &[OpTy<'tcx>],
dest: &MPlaceTy<'tcx>, dest: &MPlaceTy<'tcx>,
) -> InterpResult<'tcx, EmulateItemResult> { ) -> InterpResult<'tcx, EmulateItemResult> {
@ -45,8 +46,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
return interp_ok(EmulateItemResult::NotSupported); return interp_ok(EmulateItemResult::NotSupported);
} }
let [cb_in, a, b] = this.check_shim(abi, ExternAbi::Unadjusted, link_name, args)?; let [cb_in, a, b] = this.check_shim(abi, Conv::C, link_name, args)?;
let op = if unprefixed_name.starts_with("add") { let op = if unprefixed_name.starts_with("add") {
mir::BinOp::AddWithOverflow mir::BinOp::AddWithOverflow
} else { } else {
@ -68,9 +68,8 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
if is_u64 && this.tcx.sess.target.arch != "x86_64" { if is_u64 && this.tcx.sess.target.arch != "x86_64" {
return interp_ok(EmulateItemResult::NotSupported); return interp_ok(EmulateItemResult::NotSupported);
} }
let [c_in, a, b, out] = let [c_in, a, b, out] =
this.check_shim(abi, ExternAbi::Unadjusted, link_name, args)?; this.check_shim(abi, Conv::C, link_name, args)?;
let out = this.deref_pointer_as( let out = this.deref_pointer_as(
out, out,
if is_u64 { this.machine.layouts.u64 } else { this.machine.layouts.u32 }, if is_u64 { this.machine.layouts.u64 } else { this.machine.layouts.u32 },
@ -87,7 +86,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
// the instruction behaves like a no-op, so it is always safe to call the // the instruction behaves like a no-op, so it is always safe to call the
// intrinsic. // intrinsic.
"sse2.pause" => { "sse2.pause" => {
let [] = this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; let [] = this.check_shim(abi, Conv::C, link_name, args)?;
// Only exhibit the spin-loop hint behavior when SSE2 is enabled. // Only exhibit the spin-loop hint behavior when SSE2 is enabled.
if this.tcx.sess.unstable_target_features.contains(&Symbol::intern("sse2")) { if this.tcx.sess.unstable_target_features.contains(&Symbol::intern("sse2")) {
this.yield_active_thread(); this.yield_active_thread();
@ -107,7 +106,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
} }
let [left, right, imm] = let [left, right, imm] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C, link_name, args)?;
pclmulqdq(this, left, right, imm, dest, len)?; pclmulqdq(this, left, right, imm, dest, len)?;
} }

View file

@ -4,8 +4,9 @@
//! //!
//! [RustCrypto's sha256 module]: https://github.com/RustCrypto/hashes/blob/6be8466247e936c415d8aafb848697f39894a386/sha2/src/sha256/soft.rs //! [RustCrypto's sha256 module]: https://github.com/RustCrypto/hashes/blob/6be8466247e936c415d8aafb848697f39894a386/sha2/src/sha256/soft.rs
use rustc_abi::ExternAbi; use rustc_middle::ty::Ty;
use rustc_span::Symbol; use rustc_span::Symbol;
use rustc_target::callconv::{Conv, FnAbi};
use crate::*; use crate::*;
@ -14,7 +15,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
fn emulate_x86_sha_intrinsic( fn emulate_x86_sha_intrinsic(
&mut self, &mut self,
link_name: Symbol, link_name: Symbol,
abi: ExternAbi, abi: &FnAbi<'tcx, Ty<'tcx>>,
args: &[OpTy<'tcx>], args: &[OpTy<'tcx>],
dest: &MPlaceTy<'tcx>, dest: &MPlaceTy<'tcx>,
) -> InterpResult<'tcx, EmulateItemResult> { ) -> InterpResult<'tcx, EmulateItemResult> {
@ -52,7 +53,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
// Used to implement the _mm_sha256rnds2_epu32 function. // Used to implement the _mm_sha256rnds2_epu32 function.
"256rnds2" => { "256rnds2" => {
let [a, b, k] = let [a, b, k] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C, link_name, args)?;
let (a_reg, a_len) = this.project_to_simd(a)?; let (a_reg, a_len) = this.project_to_simd(a)?;
let (b_reg, b_len) = this.project_to_simd(b)?; let (b_reg, b_len) = this.project_to_simd(b)?;
@ -74,7 +75,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
// Used to implement the _mm_sha256msg1_epu32 function. // Used to implement the _mm_sha256msg1_epu32 function.
"256msg1" => { "256msg1" => {
let [a, b] = let [a, b] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C, link_name, args)?;
let (a_reg, a_len) = this.project_to_simd(a)?; let (a_reg, a_len) = this.project_to_simd(a)?;
let (b_reg, b_len) = this.project_to_simd(b)?; let (b_reg, b_len) = this.project_to_simd(b)?;
@ -93,7 +94,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
// Used to implement the _mm_sha256msg2_epu32 function. // Used to implement the _mm_sha256msg2_epu32 function.
"256msg2" => { "256msg2" => {
let [a, b] = let [a, b] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C, link_name, args)?;
let (a_reg, a_len) = this.project_to_simd(a)?; let (a_reg, a_len) = this.project_to_simd(a)?;
let (b_reg, b_len) = this.project_to_simd(b)?; let (b_reg, b_len) = this.project_to_simd(b)?;

View file

@ -1,6 +1,7 @@
use rustc_abi::ExternAbi;
use rustc_apfloat::ieee::Single; use rustc_apfloat::ieee::Single;
use rustc_middle::ty::Ty;
use rustc_span::Symbol; use rustc_span::Symbol;
use rustc_target::callconv::{Conv, FnAbi};
use super::{ use super::{
FloatBinOp, FloatUnaryOp, bin_op_simd_float_all, bin_op_simd_float_first, unary_op_ps, FloatBinOp, FloatUnaryOp, bin_op_simd_float_all, bin_op_simd_float_first, unary_op_ps,
@ -13,7 +14,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
fn emulate_x86_sse_intrinsic( fn emulate_x86_sse_intrinsic(
&mut self, &mut self,
link_name: Symbol, link_name: Symbol,
abi: ExternAbi, abi: &FnAbi<'tcx, Ty<'tcx>>,
args: &[OpTy<'tcx>], args: &[OpTy<'tcx>],
dest: &MPlaceTy<'tcx>, dest: &MPlaceTy<'tcx>,
) -> InterpResult<'tcx, EmulateItemResult> { ) -> InterpResult<'tcx, EmulateItemResult> {
@ -33,7 +34,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
// `right` and copies the remaining components from `left`. // `right` and copies the remaining components from `left`.
"min.ss" | "max.ss" => { "min.ss" | "max.ss" => {
let [left, right] = let [left, right] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C, link_name, args)?;
let which = match unprefixed_name { let which = match unprefixed_name {
"min.ss" => FloatBinOp::Min, "min.ss" => FloatBinOp::Min,
@ -50,7 +51,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
// semantics. // semantics.
"min.ps" | "max.ps" => { "min.ps" | "max.ps" => {
let [left, right] = let [left, right] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C, link_name, args)?;
let which = match unprefixed_name { let which = match unprefixed_name {
"min.ps" => FloatBinOp::Min, "min.ps" => FloatBinOp::Min,
@ -64,7 +65,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
// Performs the operations on the first component of `op` and // Performs the operations on the first component of `op` and
// copies the remaining components from `op`. // copies the remaining components from `op`.
"rcp.ss" | "rsqrt.ss" => { "rcp.ss" | "rsqrt.ss" => {
let [op] = this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; let [op] = this.check_shim(abi, Conv::C, link_name, args)?;
let which = match unprefixed_name { let which = match unprefixed_name {
"rcp.ss" => FloatUnaryOp::Rcp, "rcp.ss" => FloatUnaryOp::Rcp,
@ -77,7 +78,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
// Used to implement _mm_{sqrt,rcp,rsqrt}_ps functions. // Used to implement _mm_{sqrt,rcp,rsqrt}_ps functions.
// Performs the operations on all components of `op`. // Performs the operations on all components of `op`.
"rcp.ps" | "rsqrt.ps" => { "rcp.ps" | "rsqrt.ps" => {
let [op] = this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; let [op] = this.check_shim(abi, Conv::C, link_name, args)?;
let which = match unprefixed_name { let which = match unprefixed_name {
"rcp.ps" => FloatUnaryOp::Rcp, "rcp.ps" => FloatUnaryOp::Rcp,
@ -97,7 +98,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
// with hard-coded operations. // with hard-coded operations.
"cmp.ss" => { "cmp.ss" => {
let [left, right, imm] = let [left, right, imm] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C, link_name, args)?;
let which = let which =
FloatBinOp::cmp_from_imm(this, this.read_scalar(imm)?.to_i8()?, link_name)?; FloatBinOp::cmp_from_imm(this, this.read_scalar(imm)?.to_i8()?, link_name)?;
@ -114,7 +115,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
// with hard-coded operations. // with hard-coded operations.
"cmp.ps" => { "cmp.ps" => {
let [left, right, imm] = let [left, right, imm] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C, link_name, args)?;
let which = let which =
FloatBinOp::cmp_from_imm(this, this.read_scalar(imm)?.to_i8()?, link_name)?; FloatBinOp::cmp_from_imm(this, this.read_scalar(imm)?.to_i8()?, link_name)?;
@ -128,7 +129,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
| "ucomieq.ss" | "ucomilt.ss" | "ucomile.ss" | "ucomigt.ss" | "ucomige.ss" | "ucomieq.ss" | "ucomilt.ss" | "ucomile.ss" | "ucomigt.ss" | "ucomige.ss"
| "ucomineq.ss" => { | "ucomineq.ss" => {
let [left, right] = let [left, right] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C, link_name, args)?;
let (left, left_len) = this.project_to_simd(left)?; let (left, left_len) = this.project_to_simd(left)?;
let (right, right_len) = this.project_to_simd(right)?; let (right, right_len) = this.project_to_simd(right)?;
@ -156,7 +157,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
// _mm_cvtss_si64 and _mm_cvttss_si64 functions. // _mm_cvtss_si64 and _mm_cvttss_si64 functions.
// Converts the first component of `op` from f32 to i32/i64. // Converts the first component of `op` from f32 to i32/i64.
"cvtss2si" | "cvttss2si" | "cvtss2si64" | "cvttss2si64" => { "cvtss2si" | "cvttss2si" | "cvtss2si64" | "cvttss2si64" => {
let [op] = this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; let [op] = this.check_shim(abi, Conv::C, link_name, args)?;
let (op, _) = this.project_to_simd(op)?; let (op, _) = this.project_to_simd(op)?;
let op = this.read_immediate(&this.project_index(&op, 0)?)?; let op = this.read_immediate(&this.project_index(&op, 0)?)?;
@ -185,7 +186,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
// https://www.felixcloutier.com/x86/cvtsi2ss // https://www.felixcloutier.com/x86/cvtsi2ss
"cvtsi2ss" | "cvtsi642ss" => { "cvtsi2ss" | "cvtsi642ss" => {
let [left, right] = let [left, right] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C, link_name, args)?;
let (left, left_len) = this.project_to_simd(left)?; let (left, left_len) = this.project_to_simd(left)?;
let (dest, dest_len) = this.project_to_simd(dest)?; let (dest, dest_len) = this.project_to_simd(dest)?;

View file

@ -1,6 +1,7 @@
use rustc_abi::ExternAbi;
use rustc_apfloat::ieee::Double; use rustc_apfloat::ieee::Double;
use rustc_middle::ty::Ty;
use rustc_span::Symbol; use rustc_span::Symbol;
use rustc_target::callconv::{Conv, FnAbi};
use super::{ use super::{
FloatBinOp, ShiftOp, bin_op_simd_float_all, bin_op_simd_float_first, convert_float_to_int, FloatBinOp, ShiftOp, bin_op_simd_float_all, bin_op_simd_float_first, convert_float_to_int,
@ -13,7 +14,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
fn emulate_x86_sse2_intrinsic( fn emulate_x86_sse2_intrinsic(
&mut self, &mut self,
link_name: Symbol, link_name: Symbol,
abi: ExternAbi, abi: &FnAbi<'tcx, Ty<'tcx>>,
args: &[OpTy<'tcx>], args: &[OpTy<'tcx>],
dest: &MPlaceTy<'tcx>, dest: &MPlaceTy<'tcx>,
) -> InterpResult<'tcx, EmulateItemResult> { ) -> InterpResult<'tcx, EmulateItemResult> {
@ -40,7 +41,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
// intermediate 32-bit integers, and pack the results in `dest`. // intermediate 32-bit integers, and pack the results in `dest`.
"pmadd.wd" => { "pmadd.wd" => {
let [left, right] = let [left, right] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C, link_name, args)?;
let (left, left_len) = this.project_to_simd(left)?; let (left, left_len) = this.project_to_simd(left)?;
let (right, right_len) = this.project_to_simd(right)?; let (right, right_len) = this.project_to_simd(right)?;
@ -79,7 +80,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_sad_epu8 // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_sad_epu8
"psad.bw" => { "psad.bw" => {
let [left, right] = let [left, right] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C, link_name, args)?;
let (left, left_len) = this.project_to_simd(left)?; let (left, left_len) = this.project_to_simd(left)?;
let (right, right_len) = this.project_to_simd(right)?; let (right, right_len) = this.project_to_simd(right)?;
@ -118,7 +119,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
"psll.w" | "psrl.w" | "psra.w" | "psll.d" | "psrl.d" | "psra.d" | "psll.q" "psll.w" | "psrl.w" | "psra.w" | "psll.d" | "psrl.d" | "psra.d" | "psll.q"
| "psrl.q" => { | "psrl.q" => {
let [left, right] = let [left, right] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C, link_name, args)?;
let which = match unprefixed_name { let which = match unprefixed_name {
"psll.w" | "psll.d" | "psll.q" => ShiftOp::Left, "psll.w" | "psll.d" | "psll.q" => ShiftOp::Left,
@ -133,7 +134,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
// and _mm_cvttpd_epi32 functions. // and _mm_cvttpd_epi32 functions.
// Converts packed f32/f64 to packed i32. // Converts packed f32/f64 to packed i32.
"cvtps2dq" | "cvttps2dq" | "cvtpd2dq" | "cvttpd2dq" => { "cvtps2dq" | "cvttps2dq" | "cvtpd2dq" | "cvttpd2dq" => {
let [op] = this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; let [op] = this.check_shim(abi, Conv::C, link_name, args)?;
let (op_len, _) = op.layout.ty.simd_size_and_type(*this.tcx); let (op_len, _) = op.layout.ty.simd_size_and_type(*this.tcx);
let (dest_len, _) = dest.layout.ty.simd_size_and_type(*this.tcx); let (dest_len, _) = dest.layout.ty.simd_size_and_type(*this.tcx);
@ -171,7 +172,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
// vector with signed saturation. // vector with signed saturation.
"packsswb.128" => { "packsswb.128" => {
let [left, right] = let [left, right] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C, link_name, args)?;
packsswb(this, left, right, dest)?; packsswb(this, left, right, dest)?;
} }
@ -180,7 +181,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
// unsigned integer vector with saturation. // unsigned integer vector with saturation.
"packuswb.128" => { "packuswb.128" => {
let [left, right] = let [left, right] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C, link_name, args)?;
packuswb(this, left, right, dest)?; packuswb(this, left, right, dest)?;
} }
@ -189,7 +190,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
// vector with signed saturation. // vector with signed saturation.
"packssdw.128" => { "packssdw.128" => {
let [left, right] = let [left, right] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C, link_name, args)?;
packssdw(this, left, right, dest)?; packssdw(this, left, right, dest)?;
} }
@ -200,7 +201,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
// semantics. // semantics.
"min.sd" | "max.sd" => { "min.sd" | "max.sd" => {
let [left, right] = let [left, right] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C, link_name, args)?;
let which = match unprefixed_name { let which = match unprefixed_name {
"min.sd" => FloatBinOp::Min, "min.sd" => FloatBinOp::Min,
@ -217,7 +218,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
// semantics. // semantics.
"min.pd" | "max.pd" => { "min.pd" | "max.pd" => {
let [left, right] = let [left, right] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C, link_name, args)?;
let which = match unprefixed_name { let which = match unprefixed_name {
"min.pd" => FloatBinOp::Min, "min.pd" => FloatBinOp::Min,
@ -237,7 +238,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
// with hard-coded operations. // with hard-coded operations.
"cmp.sd" => { "cmp.sd" => {
let [left, right, imm] = let [left, right, imm] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C, link_name, args)?;
let which = let which =
FloatBinOp::cmp_from_imm(this, this.read_scalar(imm)?.to_i8()?, link_name)?; FloatBinOp::cmp_from_imm(this, this.read_scalar(imm)?.to_i8()?, link_name)?;
@ -254,7 +255,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
// with hard-coded operations. // with hard-coded operations.
"cmp.pd" => { "cmp.pd" => {
let [left, right, imm] = let [left, right, imm] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C, link_name, args)?;
let which = let which =
FloatBinOp::cmp_from_imm(this, this.read_scalar(imm)?.to_i8()?, link_name)?; FloatBinOp::cmp_from_imm(this, this.read_scalar(imm)?.to_i8()?, link_name)?;
@ -268,7 +269,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
| "ucomieq.sd" | "ucomilt.sd" | "ucomile.sd" | "ucomigt.sd" | "ucomige.sd" | "ucomieq.sd" | "ucomilt.sd" | "ucomile.sd" | "ucomigt.sd" | "ucomige.sd"
| "ucomineq.sd" => { | "ucomineq.sd" => {
let [left, right] = let [left, right] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C, link_name, args)?;
let (left, left_len) = this.project_to_simd(left)?; let (left, left_len) = this.project_to_simd(left)?;
let (right, right_len) = this.project_to_simd(right)?; let (right, right_len) = this.project_to_simd(right)?;
@ -296,7 +297,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
// _mm_cvtsd_si64 and _mm_cvttsd_si64 functions. // _mm_cvtsd_si64 and _mm_cvttsd_si64 functions.
// Converts the first component of `op` from f64 to i32/i64. // Converts the first component of `op` from f64 to i32/i64.
"cvtsd2si" | "cvttsd2si" | "cvtsd2si64" | "cvttsd2si64" => { "cvtsd2si" | "cvttsd2si" | "cvtsd2si64" | "cvttsd2si64" => {
let [op] = this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; let [op] = this.check_shim(abi, Conv::C, link_name, args)?;
let (op, _) = this.project_to_simd(op)?; let (op, _) = this.project_to_simd(op)?;
let op = this.read_immediate(&this.project_index(&op, 0)?)?; let op = this.read_immediate(&this.project_index(&op, 0)?)?;
@ -323,7 +324,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
// the remaining elements from `left` // the remaining elements from `left`
"cvtsd2ss" | "cvtss2sd" => { "cvtsd2ss" | "cvtss2sd" => {
let [left, right] = let [left, right] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C, link_name, args)?;
let (left, left_len) = this.project_to_simd(left)?; let (left, left_len) = this.project_to_simd(left)?;
let (right, _) = this.project_to_simd(right)?; let (right, _) = this.project_to_simd(right)?;

View file

@ -1,6 +1,7 @@
use rustc_abi::ExternAbi;
use rustc_middle::mir; use rustc_middle::mir;
use rustc_middle::ty::Ty;
use rustc_span::Symbol; use rustc_span::Symbol;
use rustc_target::callconv::{Conv, FnAbi};
use super::horizontal_bin_op; use super::horizontal_bin_op;
use crate::*; use crate::*;
@ -10,7 +11,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
fn emulate_x86_sse3_intrinsic( fn emulate_x86_sse3_intrinsic(
&mut self, &mut self,
link_name: Symbol, link_name: Symbol,
abi: ExternAbi, abi: &FnAbi<'tcx, Ty<'tcx>>,
args: &[OpTy<'tcx>], args: &[OpTy<'tcx>],
dest: &MPlaceTy<'tcx>, dest: &MPlaceTy<'tcx>,
) -> InterpResult<'tcx, EmulateItemResult> { ) -> InterpResult<'tcx, EmulateItemResult> {
@ -25,7 +26,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
// in `left` and `right`. // in `left` and `right`.
"hadd.ps" | "hadd.pd" | "hsub.ps" | "hsub.pd" => { "hadd.ps" | "hadd.pd" | "hsub.ps" | "hsub.pd" => {
let [left, right] = let [left, right] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C, link_name, args)?;
let which = match unprefixed_name { let which = match unprefixed_name {
"hadd.ps" | "hadd.pd" => mir::BinOp::Add, "hadd.ps" | "hadd.pd" => mir::BinOp::Add,
@ -42,7 +43,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
// unaligned read. // unaligned read.
"ldu.dq" => { "ldu.dq" => {
let [src_ptr] = let [src_ptr] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C, link_name, args)?;
let src_ptr = this.read_pointer(src_ptr)?; let src_ptr = this.read_pointer(src_ptr)?;
let dest = dest.force_mplace(this)?; let dest = dest.force_mplace(this)?;

View file

@ -1,5 +1,6 @@
use rustc_abi::ExternAbi; use rustc_middle::ty::Ty;
use rustc_span::Symbol; use rustc_span::Symbol;
use rustc_target::callconv::{Conv, FnAbi};
use super::{conditional_dot_product, mpsadbw, packusdw, round_all, round_first, test_bits_masked}; use super::{conditional_dot_product, mpsadbw, packusdw, round_all, round_first, test_bits_masked};
use crate::*; use crate::*;
@ -9,7 +10,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
fn emulate_x86_sse41_intrinsic( fn emulate_x86_sse41_intrinsic(
&mut self, &mut self,
link_name: Symbol, link_name: Symbol,
abi: ExternAbi, abi: &FnAbi<'tcx, Ty<'tcx>>,
args: &[OpTy<'tcx>], args: &[OpTy<'tcx>],
dest: &MPlaceTy<'tcx>, dest: &MPlaceTy<'tcx>,
) -> InterpResult<'tcx, EmulateItemResult> { ) -> InterpResult<'tcx, EmulateItemResult> {
@ -27,7 +28,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
// `i` is zeroed. // `i` is zeroed.
"insertps" => { "insertps" => {
let [left, right, imm] = let [left, right, imm] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C, link_name, args)?;
let (left, left_len) = this.project_to_simd(left)?; let (left, left_len) = this.project_to_simd(left)?;
let (right, right_len) = this.project_to_simd(right)?; let (right, right_len) = this.project_to_simd(right)?;
@ -63,7 +64,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
// the result to a 16-bit unsigned integer vector with saturation. // the result to a 16-bit unsigned integer vector with saturation.
"packusdw" => { "packusdw" => {
let [left, right] = let [left, right] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C, link_name, args)?;
packusdw(this, left, right, dest)?; packusdw(this, left, right, dest)?;
} }
@ -74,7 +75,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
// 4 bits of `imm`. // 4 bits of `imm`.
"dpps" | "dppd" => { "dpps" | "dppd" => {
let [left, right, imm] = let [left, right, imm] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C, link_name, args)?;
conditional_dot_product(this, left, right, imm, dest)?; conditional_dot_product(this, left, right, imm, dest)?;
} }
@ -83,7 +84,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
// and copies the remaining elements from `left`. // and copies the remaining elements from `left`.
"round.ss" => { "round.ss" => {
let [left, right, rounding] = let [left, right, rounding] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C, link_name, args)?;
round_first::<rustc_apfloat::ieee::Single>(this, left, right, rounding, dest)?; round_first::<rustc_apfloat::ieee::Single>(this, left, right, rounding, dest)?;
} }
@ -91,7 +92,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
// functions. Rounds the elements of `op` according to `rounding`. // functions. Rounds the elements of `op` according to `rounding`.
"round.ps" => { "round.ps" => {
let [op, rounding] = let [op, rounding] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C, link_name, args)?;
round_all::<rustc_apfloat::ieee::Single>(this, op, rounding, dest)?; round_all::<rustc_apfloat::ieee::Single>(this, op, rounding, dest)?;
} }
@ -100,7 +101,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
// and copies the remaining elements from `left`. // and copies the remaining elements from `left`.
"round.sd" => { "round.sd" => {
let [left, right, rounding] = let [left, right, rounding] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C, link_name, args)?;
round_first::<rustc_apfloat::ieee::Double>(this, left, right, rounding, dest)?; round_first::<rustc_apfloat::ieee::Double>(this, left, right, rounding, dest)?;
} }
@ -108,7 +109,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
// functions. Rounds the elements of `op` according to `rounding`. // functions. Rounds the elements of `op` according to `rounding`.
"round.pd" => { "round.pd" => {
let [op, rounding] = let [op, rounding] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C, link_name, args)?;
round_all::<rustc_apfloat::ieee::Double>(this, op, rounding, dest)?; round_all::<rustc_apfloat::ieee::Double>(this, op, rounding, dest)?;
} }
@ -116,7 +117,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
// Find the minimum unsinged 16-bit integer in `op` and // Find the minimum unsinged 16-bit integer in `op` and
// returns its value and position. // returns its value and position.
"phminposuw" => { "phminposuw" => {
let [op] = this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; let [op] = this.check_shim(abi, Conv::C, link_name, args)?;
let (op, op_len) = this.project_to_simd(op)?; let (op, op_len) = this.project_to_simd(op)?;
let (dest, dest_len) = this.project_to_simd(dest)?; let (dest, dest_len) = this.project_to_simd(dest)?;
@ -151,7 +152,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_mpsadbw_epu8 // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_mpsadbw_epu8
"mpsadbw" => { "mpsadbw" => {
let [left, right, imm] = let [left, right, imm] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C, link_name, args)?;
mpsadbw(this, left, right, imm, dest)?; mpsadbw(this, left, right, imm, dest)?;
} }
@ -161,7 +162,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
// `(op & mask) != 0 && (op & mask) != mask` // `(op & mask) != 0 && (op & mask) != mask`
"ptestz" | "ptestc" | "ptestnzc" => { "ptestz" | "ptestc" | "ptestnzc" => {
let [op, mask] = let [op, mask] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C, link_name, args)?;
let (all_zero, masked_set) = test_bits_masked(this, op, mask)?; let (all_zero, masked_set) = test_bits_masked(this, op, mask)?;
let res = match unprefixed_name { let res = match unprefixed_name {

View file

@ -1,8 +1,9 @@
use rustc_abi::{ExternAbi, Size}; use rustc_abi::Size;
use rustc_middle::mir; use rustc_middle::mir;
use rustc_middle::ty::Ty; use rustc_middle::ty::Ty;
use rustc_middle::ty::layout::LayoutOf as _; use rustc_middle::ty::layout::LayoutOf as _;
use rustc_span::Symbol; use rustc_span::Symbol;
use rustc_target::callconv::{Conv, FnAbi};
use crate::*; use crate::*;
@ -200,7 +201,7 @@ fn deconstruct_args<'tcx>(
unprefixed_name: &str, unprefixed_name: &str,
ecx: &mut MiriInterpCx<'tcx>, ecx: &mut MiriInterpCx<'tcx>,
link_name: Symbol, link_name: Symbol,
abi: ExternAbi, abi: &FnAbi<'tcx, Ty<'tcx>>,
args: &[OpTy<'tcx>], args: &[OpTy<'tcx>],
) -> InterpResult<'tcx, (OpTy<'tcx>, OpTy<'tcx>, Option<(u64, u64)>, u8)> { ) -> InterpResult<'tcx, (OpTy<'tcx>, OpTy<'tcx>, Option<(u64, u64)>, u8)> {
let array_layout_fn = |ecx: &mut MiriInterpCx<'tcx>, imm: u8| { let array_layout_fn = |ecx: &mut MiriInterpCx<'tcx>, imm: u8| {
@ -223,7 +224,7 @@ fn deconstruct_args<'tcx>(
if is_explicit { if is_explicit {
let [str1, len1, str2, len2, imm] = let [str1, len1, str2, len2, imm] =
ecx.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; ecx.check_shim(abi, Conv::C, link_name, args)?;
let imm = ecx.read_scalar(imm)?.to_u8()?; let imm = ecx.read_scalar(imm)?.to_u8()?;
let default_len = default_len::<u32>(imm); let default_len = default_len::<u32>(imm);
@ -237,7 +238,7 @@ fn deconstruct_args<'tcx>(
interp_ok((str1, str2, Some((len1, len2)), imm)) interp_ok((str1, str2, Some((len1, len2)), imm))
} else { } else {
let [str1, str2, imm] = let [str1, str2, imm] =
ecx.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; ecx.check_shim(abi, Conv::C, link_name, args)?;
let imm = ecx.read_scalar(imm)?.to_u8()?; let imm = ecx.read_scalar(imm)?.to_u8()?;
let array_layout = array_layout_fn(ecx, imm)?; let array_layout = array_layout_fn(ecx, imm)?;
@ -279,7 +280,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
fn emulate_x86_sse42_intrinsic( fn emulate_x86_sse42_intrinsic(
&mut self, &mut self,
link_name: Symbol, link_name: Symbol,
abi: ExternAbi, abi: &FnAbi<'tcx, Ty<'tcx>>,
args: &[OpTy<'tcx>], args: &[OpTy<'tcx>],
dest: &MPlaceTy<'tcx>, dest: &MPlaceTy<'tcx>,
) -> InterpResult<'tcx, EmulateItemResult> { ) -> InterpResult<'tcx, EmulateItemResult> {
@ -388,7 +389,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#ig_expand=924,925 // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#ig_expand=924,925
"pcmpistriz128" | "pcmpistris128" => { "pcmpistriz128" | "pcmpistris128" => {
let [str1, str2, imm] = let [str1, str2, imm] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C, link_name, args)?;
let imm = this.read_scalar(imm)?.to_u8()?; let imm = this.read_scalar(imm)?.to_u8()?;
let str = if unprefixed_name == "pcmpistris128" { str1 } else { str2 }; let str = if unprefixed_name == "pcmpistris128" { str1 } else { str2 };
@ -409,7 +410,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#ig_expand=1046,1047 // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#ig_expand=1046,1047
"pcmpestriz128" | "pcmpestris128" => { "pcmpestriz128" | "pcmpestris128" => {
let [_, len1, _, len2, imm] = let [_, len1, _, len2, imm] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C, link_name, args)?;
let len = if unprefixed_name == "pcmpestris128" { len1 } else { len2 }; let len = if unprefixed_name == "pcmpestris128" { len1 } else { len2 };
let len = this.read_scalar(len)?.to_i32()?; let len = this.read_scalar(len)?.to_i32()?;
let imm = this.read_scalar(imm)?.to_u8()?; let imm = this.read_scalar(imm)?.to_u8()?;
@ -437,7 +438,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
} }
let [left, right] = let [left, right] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C, link_name, args)?;
let left = this.read_scalar(left)?; let left = this.read_scalar(left)?;
let right = this.read_scalar(right)?; let right = this.read_scalar(right)?;

View file

@ -1,6 +1,7 @@
use rustc_abi::ExternAbi;
use rustc_middle::mir; use rustc_middle::mir;
use rustc_middle::ty::Ty;
use rustc_span::Symbol; use rustc_span::Symbol;
use rustc_target::callconv::{Conv, FnAbi};
use super::{horizontal_bin_op, int_abs, pmulhrsw, psign}; use super::{horizontal_bin_op, int_abs, pmulhrsw, psign};
use crate::*; use crate::*;
@ -10,7 +11,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
fn emulate_x86_ssse3_intrinsic( fn emulate_x86_ssse3_intrinsic(
&mut self, &mut self,
link_name: Symbol, link_name: Symbol,
abi: ExternAbi, abi: &FnAbi<'tcx, Ty<'tcx>>,
args: &[OpTy<'tcx>], args: &[OpTy<'tcx>],
dest: &MPlaceTy<'tcx>, dest: &MPlaceTy<'tcx>,
) -> InterpResult<'tcx, EmulateItemResult> { ) -> InterpResult<'tcx, EmulateItemResult> {
@ -23,7 +24,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
// Used to implement the _mm_abs_epi{8,16,32} functions. // Used to implement the _mm_abs_epi{8,16,32} functions.
// Calculates the absolute value of packed 8/16/32-bit integers. // Calculates the absolute value of packed 8/16/32-bit integers.
"pabs.b.128" | "pabs.w.128" | "pabs.d.128" => { "pabs.b.128" | "pabs.w.128" | "pabs.d.128" => {
let [op] = this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; let [op] = this.check_shim(abi, Conv::C, link_name, args)?;
int_abs(this, op, dest)?; int_abs(this, op, dest)?;
} }
@ -32,7 +33,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_shuffle_epi8 // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_shuffle_epi8
"pshuf.b.128" => { "pshuf.b.128" => {
let [left, right] = let [left, right] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C, link_name, args)?;
let (left, left_len) = this.project_to_simd(left)?; let (left, left_len) = this.project_to_simd(left)?;
let (right, right_len) = this.project_to_simd(right)?; let (right, right_len) = this.project_to_simd(right)?;
@ -62,7 +63,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
"phadd.w.128" | "phadd.sw.128" | "phadd.d.128" | "phsub.w.128" | "phsub.sw.128" "phadd.w.128" | "phadd.sw.128" | "phadd.d.128" | "phsub.w.128" | "phsub.sw.128"
| "phsub.d.128" => { | "phsub.d.128" => {
let [left, right] = let [left, right] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C, link_name, args)?;
let (which, saturating) = match unprefixed_name { let (which, saturating) = match unprefixed_name {
"phadd.w.128" | "phadd.d.128" => (mir::BinOp::Add, false), "phadd.w.128" | "phadd.d.128" => (mir::BinOp::Add, false),
@ -82,7 +83,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_maddubs_epi16 // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_maddubs_epi16
"pmadd.ub.sw.128" => { "pmadd.ub.sw.128" => {
let [left, right] = let [left, right] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C, link_name, args)?;
let (left, left_len) = this.project_to_simd(left)?; let (left, left_len) = this.project_to_simd(left)?;
let (right, right_len) = this.project_to_simd(right)?; let (right, right_len) = this.project_to_simd(right)?;
@ -118,7 +119,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
// https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_mulhrs_epi16 // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_mulhrs_epi16
"pmul.hr.sw.128" => { "pmul.hr.sw.128" => {
let [left, right] = let [left, right] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C, link_name, args)?;
pmulhrsw(this, left, right, dest)?; pmulhrsw(this, left, right, dest)?;
} }
@ -129,7 +130,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
// Basically, we multiply `left` with `right.signum()`. // Basically, we multiply `left` with `right.signum()`.
"psign.b.128" | "psign.w.128" | "psign.d.128" => { "psign.b.128" | "psign.w.128" | "psign.d.128" => {
let [left, right] = let [left, right] =
this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; this.check_shim(abi, Conv::C, link_name, args)?;
psign(this, left, right, dest)?; psign(this, left, right, dest)?;
} }

View file

@ -0,0 +1,30 @@
pub struct Struct {
_private: (),
}
pub trait Trait {
//@ has assoc_consts_underscore/trait.Trait.html '//pre[@class="rust item-decl"]' \
// 'const REQUIRED: Struct;'
//@ !has - '//*[@id="associatedconstant.REQUIRED"]' 'const REQUIRED: Struct = _'
//@ has - '//*[@id="associatedconstant.REQUIRED"]' 'const REQUIRED: Struct'
const REQUIRED: Struct;
//@ has - '//pre[@class="rust item-decl"]' 'const OPTIONAL: Struct = _;'
//@ has - '//*[@id="associatedconstant.OPTIONAL"]' 'const OPTIONAL: Struct = _'
const OPTIONAL: Struct = Struct { _private: () };
}
impl Trait for Struct {
//@ !has assoc_consts_underscore/struct.Struct.html '//*[@id="associatedconstant.REQUIRED"]' \
// 'const REQUIRED: Struct = _'
//@ has - '//*[@id="associatedconstant.REQUIRED"]' 'const REQUIRED: Struct'
const REQUIRED: Struct = Struct { _private: () };
//@ !has - '//*[@id="associatedconstant.OPTIONAL"]' 'const OPTIONAL: Struct = _'
//@ has - '//*[@id="associatedconstant.OPTIONAL"]' 'const OPTIONAL: Struct'
const OPTIONAL: Struct = Struct { _private: () };
}
impl Struct {
//@ !has - '//*[@id="associatedconstant.INHERENT"]' 'const INHERENT: Struct = _'
//@ has - '//*[@id="associatedconstant.INHERENT"]' 'const INHERENT: Struct'
pub const INHERENT: Struct = Struct { _private: () };
}

View file

@ -14,6 +14,6 @@ impl<const B: Word> Repr<B> {
// If we change back to rendering the value of consts, check this doesn't add // If we change back to rendering the value of consts, check this doesn't add
// a <b> tag, but escapes correctly // a <b> tag, but escapes correctly
//@ has foo/struct.Repr.html '//section[@id="associatedconstant.BASE"]/h4' '= _' //@ !has foo/struct.Repr.html '//section[@id="associatedconstant.BASE"]/h4' '='
pub const BASE: IBig = base_as_ibig::<B>(); pub const BASE: IBig = base_as_ibig::<B>();
} }