diff --git a/compiler/rustc_const_eval/src/check_consts/resolver.rs b/compiler/rustc_const_eval/src/check_consts/resolver.rs index 763c37a41aff0..79df63a9e849a 100644 --- a/compiler/rustc_const_eval/src/check_consts/resolver.rs +++ b/compiler/rustc_const_eval/src/check_consts/resolver.rs @@ -5,7 +5,7 @@ use std::fmt; use std::marker::PhantomData; -use rustc_index::bit_set::BitSet; +use rustc_index::bit_set::MixedBitSet; use rustc_middle::mir::visit::Visitor; use rustc_middle::mir::{ self, BasicBlock, CallReturnPlaces, Local, Location, Statement, StatementKind, TerminatorEdges, @@ -246,12 +246,14 @@ where } #[derive(Debug, PartialEq, Eq)] +/// The state for the `FlowSensitiveAnalysis` dataflow analysis. This domain is likely homogeneous, +/// and has a big size, so we use a bitset that can be sparse (c.f. issue #134404). pub(super) struct State { /// Describes whether a local contains qualif. - pub qualif: BitSet, + pub qualif: MixedBitSet, /// Describes whether a local's address escaped and it might become qualified as a result an /// indirect mutation. - pub borrow: BitSet, + pub borrow: MixedBitSet, } impl Clone for State { @@ -320,8 +322,8 @@ where fn bottom_value(&self, body: &mir::Body<'tcx>) -> Self::Domain { State { - qualif: BitSet::new_empty(body.local_decls.len()), - borrow: BitSet::new_empty(body.local_decls.len()), + qualif: MixedBitSet::new_empty(body.local_decls.len()), + borrow: MixedBitSet::new_empty(body.local_decls.len()), } } diff --git a/compiler/rustc_const_eval/src/const_eval/dummy_machine.rs b/compiler/rustc_const_eval/src/const_eval/dummy_machine.rs index 817acfcca74bc..46dcebc46e9c8 100644 --- a/compiler/rustc_const_eval/src/const_eval/dummy_machine.rs +++ b/compiler/rustc_const_eval/src/const_eval/dummy_machine.rs @@ -1,9 +1,11 @@ use rustc_middle::mir::interpret::{AllocId, ConstAllocation, InterpResult}; use rustc_middle::mir::*; use rustc_middle::query::TyCtxtAt; +use rustc_middle::ty::Ty; use rustc_middle::ty::layout::TyAndLayout; use rustc_middle::{bug, span_bug, ty}; use rustc_span::def_id::DefId; +use rustc_target::callconv::FnAbi; use crate::interpret::{ 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( _ecx: &mut InterpCx<'tcx, Self>, _instance: ty::Instance<'tcx>, - _abi: rustc_abi::ExternAbi, + _abi: &FnAbi<'tcx, Ty<'tcx>>, _args: &[interpret::FnArg<'tcx, Self::Provenance>], _destination: &interpret::MPlaceTy<'tcx, Self::Provenance>, _target: Option, diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs index 9c660ef0b18cb..ba7fbb254c66d 100644 --- a/compiler/rustc_const_eval/src/const_eval/machine.rs +++ b/compiler/rustc_const_eval/src/const_eval/machine.rs @@ -2,7 +2,7 @@ use std::borrow::{Borrow, Cow}; use std::fmt; use std::hash::Hash; -use rustc_abi::{Align, ExternAbi, Size}; +use rustc_abi::{Align, Size}; use rustc_ast::Mutability; use rustc_data_structures::fx::{FxHashMap, FxIndexMap, IndexEntry}; 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::{bug, mir}; use rustc_span::{Span, Symbol, sym}; +use rustc_target::callconv::FnAbi; use tracing::debug; use super::error::*; @@ -339,7 +340,7 @@ impl<'tcx> interpret::Machine<'tcx> for CompileTimeMachine<'tcx> { fn find_mir_or_eval_fn( ecx: &mut InterpCx<'tcx, Self>, orig_instance: ty::Instance<'tcx>, - _abi: ExternAbi, + _abi: &FnAbi<'tcx, Ty<'tcx>>, args: &[FnArg<'tcx>], dest: &MPlaceTy<'tcx>, ret: Option, diff --git a/compiler/rustc_const_eval/src/interpret/call.rs b/compiler/rustc_const_eval/src/interpret/call.rs index ed4a1a9e6478b..46720328ea473 100644 --- a/compiler/rustc_const_eval/src/interpret/call.rs +++ b/compiler/rustc_const_eval/src/interpret/call.rs @@ -519,7 +519,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { return M::call_extra_fn( self, extra, - caller_abi, + caller_fn_abi, args, destination, target, @@ -570,7 +570,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { let Some((body, instance)) = M::find_mir_or_eval_fn( self, instance, - caller_abi, + caller_fn_abi, args, destination, target, diff --git a/compiler/rustc_const_eval/src/interpret/machine.rs b/compiler/rustc_const_eval/src/interpret/machine.rs index 9ac2a024ccf37..36e5a2ff750ae 100644 --- a/compiler/rustc_const_eval/src/interpret/machine.rs +++ b/compiler/rustc_const_eval/src/interpret/machine.rs @@ -6,7 +6,7 @@ use std::borrow::{Borrow, Cow}; use std::fmt::Debug; use std::hash::Hash; -use rustc_abi::{Align, ExternAbi, Size}; +use rustc_abi::{Align, Size}; use rustc_apfloat::{Float, FloatConvert}; use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece}; use rustc_middle::query::TyCtxtAt; @@ -15,6 +15,7 @@ use rustc_middle::ty::layout::TyAndLayout; use rustc_middle::{mir, ty}; use rustc_span::Span; use rustc_span::def_id::DefId; +use rustc_target::callconv::FnAbi; use super::{ AllocBytes, AllocId, AllocKind, AllocRange, Allocation, CTFE_ALLOC_SALT, ConstAllocation, @@ -201,7 +202,7 @@ pub trait Machine<'tcx>: Sized { fn find_mir_or_eval_fn( ecx: &mut InterpCx<'tcx, Self>, instance: ty::Instance<'tcx>, - abi: ExternAbi, + abi: &FnAbi<'tcx, Ty<'tcx>>, args: &[FnArg<'tcx, Self::Provenance>], destination: &MPlaceTy<'tcx, Self::Provenance>, target: Option, @@ -213,7 +214,7 @@ pub trait Machine<'tcx>: Sized { fn call_extra_fn( ecx: &mut InterpCx<'tcx, Self>, fn_val: Self::ExtraFnVal, - abi: ExternAbi, + abi: &FnAbi<'tcx, Ty<'tcx>>, args: &[FnArg<'tcx, Self::Provenance>], destination: &MPlaceTy<'tcx, Self::Provenance>, target: Option, @@ -656,7 +657,7 @@ pub macro compile_time_machine(<$tcx: lifetime>) { fn call_extra_fn( _ecx: &mut InterpCx<$tcx, Self>, fn_val: !, - _abi: ExternAbi, + _abi: &FnAbi<$tcx, Ty<$tcx>>, _args: &[FnArg<$tcx>], _destination: &MPlaceTy<$tcx, Self::Provenance>, _target: Option, diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs index bc304c2b6872a..fb59955849057 100644 --- a/compiler/rustc_hir_typeck/src/method/probe.rs +++ b/compiler/rustc_hir_typeck/src/method/probe.rs @@ -1229,23 +1229,16 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { if let Some(by_value_pick) = by_value_pick { if let Ok(by_value_pick) = by_value_pick.as_ref() { if by_value_pick.kind == PickKind::InherentImplPick { - if let Err(e) = self.check_for_shadowed_autorefd_method( - by_value_pick, - step, - self_ty, - hir::Mutability::Not, - track_unstable_candidates, - ) { - 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)); + for mutbl in [hir::Mutability::Not, hir::Mutability::Mut] { + if let Err(e) = self.check_for_shadowed_autorefd_method( + by_value_pick, + step, + self_ty, + mutbl, + track_unstable_candidates, + ) { + return Some(Err(e)); + } } } } diff --git a/compiler/rustc_index/src/bit_set.rs b/compiler/rustc_index/src/bit_set.rs index aba1e93829694..664b77fd49ebf 100644 --- a/compiler/rustc_index/src/bit_set.rs +++ b/compiler/rustc_index/src/bit_set.rs @@ -1191,6 +1191,14 @@ impl MixedBitSet { } } + #[inline] + pub fn clear(&mut self) { + match self { + MixedBitSet::Small(set) => set.clear(), + MixedBitSet::Large(set) => set.clear(), + } + } + bit_relations_inherent_impls! {} } diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index 5f4b85b58a98c..55496005f4088 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -1824,7 +1824,10 @@ impl Vec { /// /// # 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: /// /// ```no_run @@ -1884,6 +1887,8 @@ impl Vec { /// /// Normally, here, one would use [`clear`] instead to correctly drop /// the contents and thus not leak memory. + /// + /// [`spare_capacity_mut()`]: Vec::spare_capacity_mut #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub unsafe fn set_len(&mut self, new_len: usize) { diff --git a/library/core/src/net/ip_addr.rs b/library/core/src/net/ip_addr.rs index 82f11f0eaac3c..7dd5c21401264 100644 --- a/library/core/src/net/ip_addr.rs +++ b/library/core/src/net/ip_addr.rs @@ -527,7 +527,7 @@ impl 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); /// ``` #[rustc_const_stable(feature = "ip_bits", since = "1.80.0")] @@ -1294,7 +1294,7 @@ impl Ipv6Addr { /// 0x1020, 0x3040, 0x5060, 0x7080, /// 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; /// - /// let addr = Ipv6Addr::from(0x102030405060708090A0B0C0D0E0F00D_u128); + /// let addr = Ipv6Addr::from_bits(0x102030405060708090A0B0C0D0E0F00D_u128); /// assert_eq!( /// Ipv6Addr::new( /// 0x1020, 0x3040, 0x5060, 0x7080, diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index de00bdf8594f1..ab65f9d6d2fcc 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -4641,7 +4641,7 @@ impl [T] { /// 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`]. /// @@ -4661,9 +4661,9 @@ impl [T] { /// let num = &nums[2]; /// /// 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)] /// @@ -4676,12 +4676,12 @@ impl [T] { /// assert_eq!(ok_elm, &[0, 1]); /// assert_eq!(weird_elm, &[1, 2]); /// - /// assert_eq!(arr.elem_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(ok_elm), Some(0)); // Points to element 0 + /// assert_eq!(arr.element_offset(weird_elm), None); // Points between element 0 and 1 /// ``` #[must_use] #[unstable(feature = "substr_range", issue = "126769")] - pub fn elem_offset(&self, element: &T) -> Option { + pub fn element_offset(&self, element: &T) -> Option { if T::IS_ZST { panic!("elements are zero-sized"); } @@ -4702,7 +4702,8 @@ impl [T] { /// 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 /// `subslice` was obtained from. To find the index of a subslice via comparison, instead use diff --git a/src/doc/rustdoc/src/unstable-features.md b/src/doc/rustdoc/src/unstable-features.md index f19c3a51f619b..d1d42e4732258 100644 --- a/src/doc/rustdoc/src/unstable-features.md +++ b/src/doc/rustdoc/src/unstable-features.md @@ -315,7 +315,7 @@ Markdown file, the URL given to `--markdown-playground-url` will take precedence `--playground-url` and `#![doc(html_playground_url = "url")]` are present when rendering crate docs, the attribute will take precedence. -### `--sort-modules-by-appearance`: control how items on module pages are sorted +## `--sort-modules-by-appearance`: control how items on module pages are sorted Using this flag looks like this: @@ -328,7 +328,7 @@ some consideration for their stability, and names that end in a number). Giving `rustdoc` will disable this sorting and instead make it print the items in the order they appear in the source. -### `--show-type-layout`: add a section to each type's docs describing its memory layout +## `--show-type-layout`: add a section to each type's docs describing its memory layout * Tracking issue: [#113248](https://github.com/rust-lang/rust/issues/113248) @@ -346,7 +346,7 @@ of that type will take in memory. Note that most layout information is **completely unstable** and may even differ between compilations. -### `--resource-suffix`: modifying the name of CSS/JavaScript in crate docs +## `--resource-suffix`: modifying the name of CSS/JavaScript in crate docs * Tracking issue: [#54765](https://github.com/rust-lang/rust/issues/54765) @@ -361,7 +361,7 @@ all these files are linked from every page, changing where they are can be cumbe specially cache them. This flag will rename all these files in the output to include the suffix in the filename. For example, `light.css` would become `light-suf.css` with the above command. -### `--extern-html-root-url`: control how rustdoc links to non-local crates +## `--extern-html-root-url`: control how rustdoc links to non-local crates Using this flag looks like this: @@ -376,7 +376,7 @@ flags to control that behavior. When the `--extern-html-root-url` flag is given one of your dependencies, rustdoc use that URL for those docs. Keep in mind that if those docs exist in the output directory, those local docs will still override this flag. -### `-Z force-unstable-if-unmarked` +## `-Z force-unstable-if-unmarked` Using this flag looks like this: @@ -389,7 +389,7 @@ This is an internal flag intended for the standard library and compiler that app allows `rustdoc` to be able to generate documentation for the compiler crates and the standard library, as an equivalent command-line argument is provided to `rustc` when building those crates. -### `--index-page`: provide a top-level landing page for docs +## `--index-page`: provide a top-level landing page for docs This feature allows you to generate an index-page with a given markdown file. A good example of it is the [rust documentation index](https://doc.rust-lang.org/nightly/index.html). @@ -398,18 +398,18 @@ With this, you'll have a page which you can customize as much as you want at the Using `index-page` option enables `enable-index-page` option as well. -### `--enable-index-page`: generate a default index page for docs +## `--enable-index-page`: generate a default index page for docs This feature allows the generation of a default index-page which lists the generated crates. -### `--nocapture`: disable output capture for test +## `--nocapture`: disable output capture for test When this flag is used with `--test`, the output (stdout and stderr) of your tests won't be captured by rustdoc. Instead, the output will be directed to your terminal, as if you had run the test executable manually. This is especially useful for debugging your tests! -### `--check`: only checks the documentation +## `--check`: only checks the documentation When this flag is supplied, rustdoc will type check and lint your code, but will not generate any documentation or run your doctests. @@ -420,7 +420,7 @@ Using this flag looks like: rustdoc -Z unstable-options --check src/lib.rs ``` -### `--static-root-path`: control how static files are loaded in HTML output +## `--static-root-path`: control how static files are loaded in HTML output Using this flag looks like this: @@ -435,7 +435,7 @@ JavaScript, and font files in a single location, rather than duplicating it once files like the search index will still load from the documentation root, but anything that gets renamed with `--resource-suffix` will load from the given path. -### `--persist-doctests`: persist doctest executables after running +## `--persist-doctests`: persist doctest executables after running * Tracking issue: [#56925](https://github.com/rust-lang/rust/issues/56925) @@ -449,7 +449,7 @@ This flag allows you to keep doctest executables around after they're compiled o Usually, rustdoc will immediately discard a compiled doctest after it's been tested, but with this option, you can keep those binaries around for farther testing. -### `--show-coverage`: calculate the percentage of items with documentation +## `--show-coverage`: calculate the percentage of items with documentation * Tracking issue: [#58154](https://github.com/rust-lang/rust/issues/58154) @@ -500,7 +500,7 @@ Calculating code examples follows these rules: * typedef 2. If one of the previously listed items has a code example, then it'll be counted. -#### JSON output +### JSON output When using `--output-format json` with this option, it will display the coverage information in JSON format. For example, here is the JSON for a file with one documented item and one @@ -522,7 +522,7 @@ Note that the third item is the crate root, which in this case is undocumented. If you want the JSON output to be displayed on `stdout` instead of having a file generated, you can use `-o -`. -### `-w`/`--output-format`: output format +## `-w`/`--output-format`: output format `--output-format json` emits documentation in the experimental [JSON format](https://doc.rust-lang.org/nightly/nightly-rustc/rustdoc_json_types/). `--output-format html` has no effect, @@ -542,7 +542,7 @@ It can also be used with `--show-coverage`. Take a look at its [documentation](#--show-coverage-calculate-the-percentage-of-items-with-documentation) for more information. -### `--enable-per-target-ignores`: allow `ignore-foo` style filters for doctests +## `--enable-per-target-ignores`: allow `ignore-foo` style filters for doctests * Tracking issue: [#64245](https://github.com/rust-lang/rust/issues/64245) @@ -577,7 +577,7 @@ struct Foo; In older versions, this will be ignored on all targets, but on newer versions `ignore-gnu` will override `ignore`. -### `--runtool`, `--runtool-arg`: program to run tests with; args to pass to it +## `--runtool`, `--runtool-arg`: program to run tests with; args to pass to it * Tracking issue: [#64245](https://github.com/rust-lang/rust/issues/64245) @@ -596,7 +596,7 @@ $ rustdoc src/lib.rs -Z unstable-options --runtool valgrind Another use case would be to run a test inside an emulator, or through a Virtual Machine. -### `--with-examples`: include examples of uses of items as documentation +## `--with-examples`: include examples of uses of items as documentation * Tracking issue: [#88791](https://github.com/rust-lang/rust/issues/88791) @@ -625,7 +625,7 @@ crate being documented (`foobar`) and a path to output the calls To scrape examples from test code, e.g. functions marked `#[test]`, then add the `--scrape-tests` flag. -### `--generate-link-to-definition`: Generate links on types in source code +## `--generate-link-to-definition`: Generate links on types in source code * Tracking issue: [#89095](https://github.com/rust-lang/rust/issues/89095) @@ -664,3 +664,80 @@ Similar to cargo `build.rustc-wrapper` option, this flag takes a `rustc` wrapper The first argument to the program will be the test builder program. This flag can be passed multiple times to nest wrappers. + +## Passing arguments to rustc when compiling doctests + +You can use the `--doctest-compilation-args` flag if you want to add options when compiling the +doctest. For example if you have: + +```rust,no_run +/// ``` +/// #![deny(warnings)] +/// #![feature(async_await)] +/// +/// let x = 12; +/// ``` +pub struct Bar; +``` + +And you run `rustdoc --test` on it, you will get: + +```console +running 1 test +test foo.rs - Bar (line 1) ... FAILED + +failures: + +---- foo.rs - Bar (line 1) stdout ---- +error: the feature `async_await` has been stable since 1.39.0 and no longer requires an attribute to enable + --> foo.rs:2:12 + | +3 | #![feature(async_await)] + | ^^^^^^^^^^^ + | +note: the lint level is defined here + --> foo.rs:1:9 + | +2 | #![deny(warnings)] + | ^^^^^^^^ + = note: `#[deny(stable_features)]` implied by `#[deny(warnings)]` + +error: aborting due to 1 previous error + +Couldn't compile the test. + +failures: + foo.rs - Bar (line 1) + +test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.03s +``` + +But if you can limit the lint level to warning by using `--doctest_compilation_args=--cap-lints=warn`: + +```console +$ rustdoc --test --doctest_compilation_args=--cap-lints=warn file.rs + +running 1 test +test tests/rustdoc-ui/doctest/rustflags.rs - Bar (line 5) ... ok + +test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.06s +``` + +The parsing of arguments works as follows: if it encounters a `"` or a `'`, it will continue +until it finds the character unescaped (without a prepending `\`). If not inside a string, a +whitespace character will also split arguments. Example: + +```text +"hello 'a'\" ok" how are 'you today?' +``` + +will be split as follows: + +```text +[ + "hello 'a'\" ok", + "how", + "are", + "you today?", +] +``` diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index ffec5dc5c58e2..9d0c0f687c706 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -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(); cx.with_param_env(local_did, |cx| { let inner = match trait_item.kind { - hir::TraitItemKind::Const(ty, Some(default)) => AssocConstItem(Box::new(Constant { - generics: enter_impl_trait(cx, |cx| clean_generics(trait_item.generics, cx)), - kind: ConstantKind::Local { def_id: local_did, body: default }, - type_: clean_ty(ty, cx), - })), + hir::TraitItemKind::Const(ty, Some(default)) => { + ProvidedAssocConstItem(Box::new(Constant { + generics: enter_impl_trait(cx, |cx| clean_generics(trait_item.generics, cx)), + kind: ConstantKind::Local { def_id: local_did, body: default }, + type_: clean_ty(ty, cx), + })) + } hir::TraitItemKind::Const(ty, None) => { 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)) => { 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)) => { let m = clean_function(cx, sig, trait_item.generics, FunctionArgs::Names(names)); - TyMethodItem(m) + RequiredMethodItem(m) } hir::TraitItemKind::Type(bounds, Some(default)) => { 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) => { 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(); - TyAssocTypeItem(generics, bounds) + RequiredAssocTypeItem(generics, bounds) } }; 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(); cx.with_param_env(local_did, |cx| { 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), kind: ConstantKind::Local { def_id: local_did, body: expr }, 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); - let provided = match assoc_item.container { - ty::AssocItemContainer::Impl => true, - ty::AssocItemContainer::Trait => tcx.defaultness(assoc_item.def_id).has_value(), - }; - if provided { - AssocConstItem(Box::new(Constant { + match assoc_item.container { + ty::AssocItemContainer::Impl => ImplAssocConstItem(Box::new(Constant { generics, kind: ConstantKind::Extern { def_id: assoc_item.def_id }, type_: ty, - })) - } else { - TyAssocConstItem(generics, Box::new(ty)) + })), + ty::AssocItemContainer::Trait => { + 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 => { @@ -1369,7 +1376,7 @@ pub(crate) fn clean_middle_assoc_item(assoc_item: &ty::AssocItem, cx: &mut DocCo }; MethodItem(item, defaultness) } else { - TyMethodItem(item) + RequiredMethodItem(item) } } ty::AssocKind::Type => { @@ -1486,7 +1493,7 @@ pub(crate) fn clean_middle_assoc_item(assoc_item: &ty::AssocItem, cx: &mut DocCo bounds, ) } else { - TyAssocTypeItem(generics, bounds) + RequiredAssocTypeItem(generics, bounds) } } else { AssocTypeItem( diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 64d99b1d226be..8c7ab925577df 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -545,14 +545,14 @@ impl Item { pub(crate) fn is_associated_type(&self) -> bool { matches!(self.kind, AssocTypeItem(..) | StrippedItem(box AssocTypeItem(..))) } - pub(crate) fn is_ty_associated_type(&self) -> bool { - matches!(self.kind, TyAssocTypeItem(..) | StrippedItem(box TyAssocTypeItem(..))) + pub(crate) fn is_required_associated_type(&self) -> bool { + matches!(self.kind, RequiredAssocTypeItem(..) | StrippedItem(box RequiredAssocTypeItem(..))) } 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 { - matches!(self.kind, TyAssocConstItem(..) | StrippedItem(box TyAssocConstItem(..))) + pub(crate) fn is_required_associated_const(&self) -> bool { + matches!(self.kind, RequiredAssocConstItem(..) | StrippedItem(box RequiredAssocConstItem(..))) } pub(crate) fn is_method(&self) -> bool { self.type_() == ItemType::Method @@ -669,7 +669,9 @@ impl Item { asyncness: hir::IsAsync::NotAsync, } } - ItemKind::FunctionItem(_) | ItemKind::MethodItem(_, _) | ItemKind::TyMethodItem(_) => { + ItemKind::FunctionItem(_) + | ItemKind::MethodItem(_, _) + | ItemKind::RequiredMethodItem(_) => { let def_id = self.def_id().unwrap(); build_fn_header(def_id, tcx, tcx.asyncness(def_id)) } @@ -699,8 +701,13 @@ impl Item { // Variants always inherit visibility VariantItem(..) | ImplItem(..) => return None, // Trait items inherit the trait's visibility - AssocConstItem(..) | TyAssocConstItem(..) | AssocTypeItem(..) | TyAssocTypeItem(..) - | TyMethodItem(..) | MethodItem(..) => { + RequiredAssocConstItem(..) + | ProvidedAssocConstItem(..) + | ImplAssocConstItem(..) + | AssocTypeItem(..) + | RequiredAssocTypeItem(..) + | RequiredMethodItem(..) + | MethodItem(..) => { let assoc_item = tcx.associated_item(def_id); let is_trait_item = match assoc_item.container { ty::AssocItemContainer::Trait => true, @@ -845,10 +852,10 @@ pub(crate) enum ItemKind { TraitAliasItem(TraitAlias), ImplItem(Box), /// A required method in a trait declaration meaning it's only a function signature. - TyMethodItem(Box), + RequiredMethodItem(Box), /// 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, Option), StructFieldItem(Type), VariantItem(Variant), @@ -862,14 +869,16 @@ pub(crate) enum ItemKind { ProcMacroItem(ProcMacro), PrimitiveItem(PrimitiveType), /// A required associated constant in a trait declaration. - TyAssocConstItem(Generics, Box), + RequiredAssocConstItem(Generics, Box), ConstantItem(Box), - /// An associated constant in a trait impl or a provided one in a trait declaration. - AssocConstItem(Box), + /// An associated constant in a trait declaration with provided default value. + ProvidedAssocConstItem(Box), + /// An associated constant in an inherent impl or trait impl. + ImplAssocConstItem(Box), /// A required associated type in a trait declaration. /// /// The bounds may be non-empty if there is a `where` clause. - TyAssocTypeItem(Generics, Vec), + RequiredAssocTypeItem(Generics, Vec), /// An associated type in a trait impl or a provided one in a trait declaration. AssocTypeItem(Box, Vec), /// An item that has been stripped by a rustdoc pass @@ -900,7 +909,7 @@ impl ItemKind { | StaticItem(_) | ConstantItem(_) | TraitAliasItem(_) - | TyMethodItem(_) + | RequiredMethodItem(_) | MethodItem(_, _) | StructFieldItem(_) | ForeignFunctionItem(_, _) @@ -909,9 +918,10 @@ impl ItemKind { | MacroItem(_) | ProcMacroItem(_) | PrimitiveItem(_) - | TyAssocConstItem(..) - | AssocConstItem(..) - | TyAssocTypeItem(..) + | RequiredAssocConstItem(..) + | ProvidedAssocConstItem(..) + | ImplAssocConstItem(..) + | RequiredAssocTypeItem(..) | AssocTypeItem(..) | StrippedItem(_) | KeywordItem => [].iter(), diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs index 34c91e33db700..af3c7cc7be345 100644 --- a/src/librustdoc/config.rs +++ b/src/librustdoc/config.rs @@ -172,6 +172,9 @@ pub(crate) struct Options { /// This is mainly useful for other tools that reads that debuginfo to figure out /// how to call the compiler with the same arguments. pub(crate) expanded_args: Vec, + + /// Arguments to be used when compiling doctests. + pub(crate) doctest_compilation_args: Vec, } impl fmt::Debug for Options { @@ -774,6 +777,7 @@ impl Options { let scrape_examples_options = ScrapeExamplesOptions::new(matches, dcx); let with_examples = matches.opt_strs("with-examples"); let call_locations = crate::scrape_examples::load_call_locations(with_examples, dcx); + let doctest_compilation_args = matches.opt_strs("doctest-compilation-args"); let unstable_features = rustc_feature::UnstableFeatures::from_environment(crate_name.as_deref()); @@ -819,6 +823,7 @@ impl Options { scrape_examples_options, unstable_features, expanded_args: args, + doctest_compilation_args, }; let render_options = RenderOptions { output, diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs index ce44cb1c319aa..e6e5123d0bba0 100644 --- a/src/librustdoc/doctest.rs +++ b/src/librustdoc/doctest.rs @@ -50,6 +50,46 @@ pub(crate) struct GlobalTestOptions { pub(crate) args_file: PathBuf, } +/// Function used to split command line arguments just like a shell would. +fn split_args(args: &str) -> Vec { + let mut out = Vec::new(); + let mut iter = args.chars(); + let mut current = String::new(); + + while let Some(c) = iter.next() { + if c == '\\' { + if let Some(c) = iter.next() { + // If it's escaped, even a quote or a whitespace will be ignored. + current.push(c); + } + } else if c == '"' || c == '\'' { + while let Some(new_c) = iter.next() { + if new_c == c { + break; + } else if new_c == '\\' { + if let Some(c) = iter.next() { + // If it's escaped, even a quote will be ignored. + current.push(c); + } + } else { + current.push(new_c); + } + } + } else if " \n\t\r".contains(c) { + if !current.is_empty() { + out.push(current.clone()); + current.clear(); + } + } else { + current.push(c); + } + } + if !current.is_empty() { + out.push(current); + } + out +} + pub(crate) fn generate_args_file(file_path: &Path, options: &RustdocOptions) -> Result<(), String> { let mut file = File::create(file_path) .map_err(|error| format!("failed to create args file: {error:?}"))?; @@ -78,6 +118,10 @@ pub(crate) fn generate_args_file(file_path: &Path, options: &RustdocOptions) -> content.push(format!("-Z{unstable_option_str}")); } + for compilation_args in &options.doctest_compilation_args { + content.extend(split_args(compilation_args)); + } + let content = content.join("\n"); file.write_all(content.as_bytes()) diff --git a/src/librustdoc/doctest/tests.rs b/src/librustdoc/doctest/tests.rs index 160d0f222b4e0..fa6cca3681be5 100644 --- a/src/librustdoc/doctest/tests.rs +++ b/src/librustdoc/doctest/tests.rs @@ -379,3 +379,25 @@ fn main() { let (output, len) = make_test(input, None, false, &opts, None); assert_eq!((output, len), (expected, 1)); } + +#[test] +fn check_split_args() { + fn compare(input: &str, expected: &[&str]) { + let output = super::split_args(input); + let expected = expected.iter().map(|s| s.to_string()).collect::>(); + assert_eq!(expected, output, "test failed for {input:?}"); + } + + compare("'a' \"b\"c", &["a", "bc"]); + compare("'a' \"b \"c d", &["a", "b c", "d"]); + compare("'a' \"b\\\"c\"", &["a", "b\"c"]); + compare("'a\"'", &["a\""]); + compare("\"a'\"", &["a'"]); + compare("\\ a", &[" a"]); + compare("\\\\", &["\\"]); + compare("a'", &["a"]); + compare("a ", &["a"]); + compare("a b", &["a", "b"]); + compare("a\n\t \rb", &["a", "b"]); + compare("a\n\t1 \rb", &["a", "1", "b"]); +} diff --git a/src/librustdoc/fold.rs b/src/librustdoc/fold.rs index 95e495205aea6..c03d16ad081bf 100644 --- a/src/librustdoc/fold.rs +++ b/src/librustdoc/fold.rs @@ -82,7 +82,7 @@ pub(crate) trait DocFolder: Sized { | StaticItem(_) | ConstantItem(..) | TraitAliasItem(_) - | TyMethodItem(_) + | RequiredMethodItem(_) | MethodItem(_, _) | StructFieldItem(_) | ForeignFunctionItem(..) @@ -91,9 +91,10 @@ pub(crate) trait DocFolder: Sized { | MacroItem(_) | ProcMacroItem(_) | PrimitiveItem(_) - | TyAssocConstItem(..) - | AssocConstItem(..) - | TyAssocTypeItem(..) + | RequiredAssocConstItem(..) + | ProvidedAssocConstItem(..) + | ImplAssocConstItem(..) + | RequiredAssocTypeItem(..) | AssocTypeItem(..) | KeywordItem => kind, } diff --git a/src/librustdoc/formats/cache.rs b/src/librustdoc/formats/cache.rs index e387eb010bebd..b63122565c429 100644 --- a/src/librustdoc/formats/cache.rs +++ b/src/librustdoc/formats/cache.rs @@ -334,12 +334,13 @@ impl DocFolder for CacheBuilder<'_, '_> { clean::ExternCrateItem { .. } | clean::ImportItem(..) | clean::ImplItem(..) - | clean::TyMethodItem(..) + | clean::RequiredMethodItem(..) | clean::MethodItem(..) | clean::StructFieldItem(..) - | clean::TyAssocConstItem(..) - | clean::AssocConstItem(..) - | clean::TyAssocTypeItem(..) + | clean::RequiredAssocConstItem(..) + | clean::ProvidedAssocConstItem(..) + | clean::ImplAssocConstItem(..) + | clean::RequiredAssocTypeItem(..) | clean::AssocTypeItem(..) | clean::StrippedItem(..) | 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 (parent_did, parent_path) = match item.kind { 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()) => { // skip associated items in trait impls return; } - clean::TyMethodItem(..) - | clean::TyAssocConstItem(..) - | clean::TyAssocTypeItem(..) + clean::RequiredMethodItem(..) + | clean::RequiredAssocConstItem(..) + | clean::RequiredAssocTypeItem(..) | clean::StructFieldItem(..) | clean::VariantItem(..) => { // 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]; (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 parent_did = match last { // impl Trait for &T { fn method(self); } diff --git a/src/librustdoc/formats/item_type.rs b/src/librustdoc/formats/item_type.rs index 383e3135faa86..de6537e992f19 100644 --- a/src/librustdoc/formats/item_type.rs +++ b/src/librustdoc/formats/item_type.rs @@ -88,7 +88,7 @@ impl<'a> From<&'a clean::Item> for ItemType { clean::ConstantItem(..) => ItemType::Constant, clean::TraitItem(..) => ItemType::Trait, clean::ImplItem(..) => ItemType::Impl, - clean::TyMethodItem(..) => ItemType::TyMethod, + clean::RequiredMethodItem(..) => ItemType::TyMethod, clean::MethodItem(..) => ItemType::Method, clean::StructFieldItem(..) => ItemType::StructField, clean::VariantItem(..) => ItemType::Variant, @@ -96,8 +96,10 @@ impl<'a> From<&'a clean::Item> for ItemType { clean::ForeignStaticItem(..) => ItemType::Static, // no ForeignStatic clean::MacroItem(..) => ItemType::Macro, clean::PrimitiveItem(..) => ItemType::Primitive, - clean::TyAssocConstItem(..) | clean::AssocConstItem(..) => ItemType::AssocConst, - clean::TyAssocTypeItem(..) | clean::AssocTypeItem(..) => ItemType::AssocType, + clean::RequiredAssocConstItem(..) + | clean::ProvidedAssocConstItem(..) + | clean::ImplAssocConstItem(..) => ItemType::AssocConst, + clean::RequiredAssocTypeItem(..) | clean::AssocTypeItem(..) => ItemType::AssocType, clean::ForeignTypeItem => ItemType::ForeignType, clean::KeywordItem => ItemType::Keyword, clean::TraitAliasItem(..) => ItemType::TraitAlias, diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index eb9f39128bcb8..dfdf2cd6ec32b 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -836,12 +836,23 @@ fn assoc_href_attr(it: &clean::Item, link: AssocItemLink<'_>, cx: &Context<'_>) 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( w: &mut Buffer, it: &clean::Item, generics: &clean::Generics, ty: &clean::Type, - default: Option<&clean::ConstantKind>, + value: AssocConstValue<'_>, link: AssocItemLink<'_>, indent: usize, cx: &Context<'_>, @@ -857,15 +868,20 @@ fn assoc_const( generics = generics.print(cx), ty = ty.print(cx), ); - if let Some(default) = default { - w.write_str(" = "); - + if let AssocConstValue::TraitDefault(konst) | AssocConstValue::Impl(konst) = value { // FIXME: `.value()` uses `clean::utils::format_integer_with_underscore_sep` under the // hood which adds noisy underscores and a type suffix to number literals. // This hurts readability in this context especially when more complex expressions // are involved and it doesn't add much of value. // 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)); } @@ -1076,33 +1092,43 @@ fn render_assoc_item( ) { match &item.kind { clean::StrippedItem(..) => {} - clean::TyMethodItem(m) => { + clean::RequiredMethodItem(m) => { assoc_method(w, item, &m.generics, &m.decl, link, parent, cx, render_mode) } clean::MethodItem(m, _) => { 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, item, generics, ty, - None, + AssocConstValue::None, + link, + if parent == ItemType::Trait { 4 } else { 0 }, + cx, + ), + clean::ProvidedAssocConstItem(ci) => assoc_const( + w, + item, + &ci.generics, + &ci.type_, + AssocConstValue::TraitDefault(&ci.kind), link, if parent == ItemType::Trait { 4 } else { 0 }, cx, ), - clean::AssocConstItem(ci) => assoc_const( + clean::ImplAssocConstItem(ci) => assoc_const( w, item, &ci.generics, &ci.type_, - Some(&ci.kind), + AssocConstValue::Impl(&ci.kind), link, if parent == ItemType::Trait { 4 } else { 0 }, cx, ), - clean::TyAssocTypeItem(ref generics, ref bounds) => assoc_type( + clean::RequiredAssocTypeItem(ref generics, ref bounds) => assoc_type( w, item, generics, @@ -1384,7 +1410,7 @@ fn render_deref_methods( fn should_render_item(item: &clean::Item, deref_mut_: bool, tcx: TyCtxt<'_>) -> bool { let self_type_opt = match item.kind { 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, }; @@ -1660,7 +1686,7 @@ fn render_impl( write!(w, "
"); } match &item.kind { - clean::MethodItem(..) | clean::TyMethodItem(_) => { + clean::MethodItem(..) | clean::RequiredMethodItem(_) => { // Only render when the method is not static or we allow static methods if render_method_item { let id = cx.derive_id(format!("{item_type}.{name}")); @@ -1690,7 +1716,7 @@ fn render_impl( w.write_str(""); } } - clean::TyAssocConstItem(ref generics, ref ty) => { + clean::RequiredAssocConstItem(ref generics, ref ty) => { let source_id = format!("{item_type}.{name}"); let id = cx.derive_id(&source_id); write!(w, "
"); @@ -1705,14 +1731,14 @@ fn render_impl( item, generics, ty, - None, + AssocConstValue::None, link.anchor(if trait_.is_some() { &source_id } else { &id }), 0, cx, ); w.write_str("
"); } - clean::AssocConstItem(ci) => { + clean::ProvidedAssocConstItem(ci) | clean::ImplAssocConstItem(ci) => { let source_id = format!("{item_type}.{name}"); let id = cx.derive_id(&source_id); write!(w, "
"); @@ -1727,14 +1753,18 @@ fn render_impl( item, &ci.generics, &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 }), 0, cx, ); w.write_str("
"); } - clean::TyAssocTypeItem(ref generics, ref bounds) => { + clean::RequiredAssocTypeItem(ref generics, ref bounds) => { let source_id = format!("{item_type}.{name}"); let id = cx.derive_id(&source_id); write!(w, "
"); @@ -1809,11 +1839,13 @@ fn render_impl( if !impl_.is_negative_trait_impl() { for trait_item in &impl_.items { match trait_item.kind { - clean::MethodItem(..) | clean::TyMethodItem(_) => methods.push(trait_item), - clean::TyAssocTypeItem(..) | clean::AssocTypeItem(..) => { + clean::MethodItem(..) | clean::RequiredMethodItem(_) => methods.push(trait_item), + clean::RequiredAssocTypeItem(..) | clean::AssocTypeItem(..) => { 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. doc_impl_item( &mut default_impl_items, diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index ced9ff2d68542..0fb77d38f1653 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -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) { let tcx = cx.tcx(); let bounds = bounds(&t.bounds, false, cx); - let required_types = t.items.iter().filter(|m| m.is_ty_associated_type()).collect::>(); + let required_types = + t.items.iter().filter(|m| m.is_required_associated_type()).collect::>(); let provided_types = t.items.iter().filter(|m| m.is_associated_type()).collect::>(); - let required_consts = t.items.iter().filter(|m| m.is_ty_associated_const()).collect::>(); + let required_consts = + t.items.iter().filter(|m| m.is_required_associated_const()).collect::>(); let provided_consts = t.items.iter().filter(|m| m.is_associated_const()).collect::>(); let required_methods = t.items.iter().filter(|m| m.is_ty_method()).collect::>(); let provided_methods = t.items.iter().filter(|m| m.is_method()).collect::>(); diff --git a/src/librustdoc/html/render/search_index.rs b/src/librustdoc/html/render/search_index.rs index 2c26ffa76f6a8..fe2e155c9ba7a 100644 --- a/src/librustdoc/html/render/search_index.rs +++ b/src/librustdoc/html/render/search_index.rs @@ -837,7 +837,7 @@ pub(crate) fn get_function_type_for_search( clean::ForeignFunctionItem(ref f, _) | clean::FunctionItem(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) } _ => return None, @@ -1207,10 +1207,11 @@ fn simplify_fn_type<'a, 'tcx>( && let Type::Path { path } = arg && let def_id = path.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 { - 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 idx = -isize::try_from(rgen.len() + 1).unwrap(); diff --git a/src/librustdoc/html/render/sidebar.rs b/src/librustdoc/html/render/sidebar.rs index e99e2f04b2c5e..af39d15f67175 100644 --- a/src/librustdoc/html/render/sidebar.rs +++ b/src/librustdoc/html/render/sidebar.rs @@ -282,10 +282,10 @@ fn sidebar_trait<'a>( 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 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 = filter_items(&t.items, |m| m.is_associated_const(), "associatedconstant"); let req_method = filter_items(&t.items, |m| m.is_ty_method(), "tymethod"); diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs index 12f68f6042666..583d0214a4689 100644 --- a/src/librustdoc/json/conversions.rs +++ b/src/librustdoc/json/conversions.rs @@ -319,7 +319,9 @@ fn from_clean_item(item: clean::Item, renderer: &JsonRenderer<'_>) -> ItemEnum { TraitItem(t) => ItemEnum::Trait((*t).into_json(renderer)), TraitAliasItem(t) => ItemEnum::TraitAlias(t.into_json(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)), StaticItem(s) => ItemEnum::Static(convert_static(s, rustc_hir::Safety::Safe, 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. - TyAssocConstItem(_generics, ty) => { + RequiredAssocConstItem(_generics, ty) => { ItemEnum::AssocConst { type_: (*ty).into_json(renderer), value: None } } // 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), value: Some(ci.kind.expr(renderer.tcx)), }, - TyAssocTypeItem(g, b) => ItemEnum::AssocType { + RequiredAssocTypeItem(g, b) => ItemEnum::AssocType { generics: g.into_json(renderer), bounds: b.into_json(renderer), type_: None, diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 7655c2e0e15e1..ff1c9c61720fa 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -642,6 +642,15 @@ fn opts() -> Vec { "Includes trait implementations and other crate info from provided path. Only use with --merge=finalize", "path/to/doc.parts/", ), + opt(Unstable, Flag, "", "html-no-source", "Disable HTML source code pages generation", ""), + opt( + Unstable, + Multi, + "", + "doctest-compilation-args", + "", + "add arguments to be used when compiling doctests", + ), // deprecated / removed options opt(Unstable, FlagMulti, "", "disable-minification", "removed", ""), opt( @@ -684,7 +693,6 @@ fn opts() -> Vec { "removed, see issue #44136 for more information", "[rust]", ), - opt(Unstable, Flag, "", "html-no-source", "Disable HTML source code pages generation", ""), ] } diff --git a/src/librustdoc/passes/check_doc_test_visibility.rs b/src/librustdoc/passes/check_doc_test_visibility.rs index c288a3cf2a475..0fefd13f76333 100644 --- a/src/librustdoc/passes/check_doc_test_visibility.rs +++ b/src/librustdoc/passes/check_doc_test_visibility.rs @@ -72,10 +72,11 @@ pub(crate) fn should_have_doc_example(cx: &DocContext<'_>, item: &clean::Item) - | clean::ForeignFunctionItem(..) | clean::ForeignStaticItem(..) | clean::ForeignTypeItem - | clean::AssocConstItem(..) | clean::AssocTypeItem(..) - | clean::TyAssocConstItem(..) - | clean::TyAssocTypeItem(..) + | clean::RequiredAssocConstItem(..) + | clean::ProvidedAssocConstItem(..) + | clean::ImplAssocConstItem(..) + | clean::RequiredAssocTypeItem(..) // check for trait impl | clean::ImplItem(box clean::Impl { trait_: Some(_), .. }) ) diff --git a/src/librustdoc/passes/propagate_stability.rs b/src/librustdoc/passes/propagate_stability.rs index d924be2edce28..4c682c3d4ca05 100644 --- a/src/librustdoc/passes/propagate_stability.rs +++ b/src/librustdoc/passes/propagate_stability.rs @@ -67,11 +67,12 @@ impl DocFolder for StabilityPropagator<'_, '_> { // Don't inherit the parent's stability for these items, because they // are potentially accessible even if the parent is more unstable. ItemKind::ImplItem(..) - | ItemKind::TyMethodItem(..) + | ItemKind::RequiredMethodItem(..) | ItemKind::MethodItem(..) - | ItemKind::TyAssocConstItem(..) - | ItemKind::AssocConstItem(..) - | ItemKind::TyAssocTypeItem(..) + | ItemKind::RequiredAssocConstItem(..) + | ItemKind::ProvidedAssocConstItem(..) + | ItemKind::ImplAssocConstItem(..) + | ItemKind::RequiredAssocTypeItem(..) | ItemKind::AssocTypeItem(..) | ItemKind::PrimitiveItem(..) | ItemKind::KeywordItem => own_stability, diff --git a/src/librustdoc/passes/stripper.rs b/src/librustdoc/passes/stripper.rs index 60909754b3330..eedbbca0f8dfc 100644 --- a/src/librustdoc/passes/stripper.rs +++ b/src/librustdoc/passes/stripper.rs @@ -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; if item_id.is_local() && !self.effective_visibilities.is_reachable(self.tcx, item_id.expect_def_id()) @@ -118,7 +121,9 @@ impl DocFolder for Stripper<'_, '_> { clean::ImplItem(..) => {} // tymethods etc. have no control over privacy - clean::TyMethodItem(..) | clean::TyAssocConstItem(..) | clean::TyAssocTypeItem(..) => {} + clean::RequiredMethodItem(..) + | clean::RequiredAssocConstItem(..) + | clean::RequiredAssocTypeItem(..) => {} // Proc-macros are always public clean::ProcMacroItem(..) => {} diff --git a/src/librustdoc/visit.rs b/src/librustdoc/visit.rs index c2e8ffd7665b8..b8b619514aad9 100644 --- a/src/librustdoc/visit.rs +++ b/src/librustdoc/visit.rs @@ -35,7 +35,7 @@ pub(crate) trait DocVisitor<'a>: Sized { | StaticItem(_) | ConstantItem(..) | TraitAliasItem(_) - | TyMethodItem(_) + | RequiredMethodItem(_) | MethodItem(_, _) | StructFieldItem(_) | ForeignFunctionItem(..) @@ -44,9 +44,10 @@ pub(crate) trait DocVisitor<'a>: Sized { | MacroItem(_) | ProcMacroItem(_) | PrimitiveItem(_) - | TyAssocConstItem(..) - | AssocConstItem(..) - | TyAssocTypeItem(..) + | RequiredAssocConstItem(..) + | ProvidedAssocConstItem(..) + | ImplAssocConstItem(..) + | RequiredAssocTypeItem(..) | AssocTypeItem(..) | KeywordItem => {} } diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version index 10108a6fbca0d..64ce886239634 100644 --- a/src/tools/miri/rust-version +++ b/src/tools/miri/rust-version @@ -1 +1 @@ -214587c89d527dd0ccbe1f2150c737d3bdee67b0 +8a1f8039a7ded79d3d4fe97b110016d89f2b11e2 diff --git a/src/tools/miri/src/helpers.rs b/src/tools/miri/src/helpers.rs index 9927f3f3f977d..444ff72513963 100644 --- a/src/tools/miri/src/helpers.rs +++ b/src/tools/miri/src/helpers.rs @@ -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_session::config::CrateType; use rustc_span::{Span, Symbol}; +use rustc_target::callconv::{Conv, FnAbi}; use crate::*; @@ -920,13 +921,13 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { } /// Check that the ABI is what we expect. - fn check_abi<'a>(&self, abi: ExternAbi, exp_abi: ExternAbi) -> InterpResult<'a, ()> { - if abi != exp_abi { + fn check_abi<'a>(&self, fn_abi: &FnAbi<'tcx, Ty<'tcx>>, exp_abi: Conv) -> InterpResult<'a, ()> { + if fn_abi.conv != exp_abi { throw_ub_format!( - "calling a function with ABI {} using caller ABI {}", - exp_abi.name(), - abi.name() - ) + "calling a function with ABI {:?} using caller ABI {:?}", + exp_abi, + fn_abi.conv + ); } interp_ok(()) } @@ -956,8 +957,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { fn check_abi_and_shim_symbol_clash( &mut self, - abi: ExternAbi, - exp_abi: ExternAbi, + abi: &FnAbi<'tcx, Ty<'tcx>>, + exp_abi: Conv, link_name: Symbol, ) -> InterpResult<'tcx, ()> { self.check_abi(abi, exp_abi)?; @@ -981,8 +982,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { fn check_shim<'a, const N: usize>( &mut self, - abi: ExternAbi, - exp_abi: ExternAbi, + abi: &FnAbi<'tcx, Ty<'tcx>>, + exp_abi: Conv, link_name: Symbol, args: &'a [OpTy<'tcx>], ) -> InterpResult<'tcx, &'a [OpTy<'tcx>; N]> diff --git a/src/tools/miri/src/machine.rs b/src/tools/miri/src/machine.rs index ad8a7ea1668da..33cefd607646a 100644 --- a/src/tools/miri/src/machine.rs +++ b/src/tools/miri/src/machine.rs @@ -24,6 +24,7 @@ use rustc_middle::ty::{self, Instance, Ty, TyCtxt}; use rustc_session::config::InliningThreshold; use rustc_span::def_id::{CrateNum, DefId}; use rustc_span::{Span, SpanData, Symbol}; +use rustc_target::callconv::FnAbi; use crate::concurrency::cpu_affinity::{self, CpuAffinityMask}; use crate::concurrency::data_race::{self, NaReadType, NaWriteType}; @@ -1010,7 +1011,7 @@ impl<'tcx> Machine<'tcx> for MiriMachine<'tcx> { fn find_mir_or_eval_fn( ecx: &mut MiriInterpCx<'tcx>, instance: ty::Instance<'tcx>, - abi: ExternAbi, + abi: &FnAbi<'tcx, Ty<'tcx>>, args: &[FnArg<'tcx, Provenance>], dest: &MPlaceTy<'tcx>, ret: Option, @@ -1037,7 +1038,7 @@ impl<'tcx> Machine<'tcx> for MiriMachine<'tcx> { fn call_extra_fn( ecx: &mut MiriInterpCx<'tcx>, fn_val: DynSym, - abi: ExternAbi, + abi: &FnAbi<'tcx, Ty<'tcx>>, args: &[FnArg<'tcx, Provenance>], dest: &MPlaceTy<'tcx>, ret: Option, diff --git a/src/tools/miri/src/shims/backtrace.rs b/src/tools/miri/src/shims/backtrace.rs index c7b399228bfb4..1622ef280d25c 100644 --- a/src/tools/miri/src/shims/backtrace.rs +++ b/src/tools/miri/src/shims/backtrace.rs @@ -1,7 +1,8 @@ -use rustc_abi::{ExternAbi, Size}; +use rustc_abi::Size; use rustc_middle::ty::layout::LayoutOf as _; use rustc_middle::ty::{self, Instance, Ty}; use rustc_span::{BytePos, Loc, Symbol, hygiene}; +use rustc_target::callconv::{Conv, FnAbi}; use crate::helpers::check_min_arg_count; use crate::*; @@ -10,13 +11,13 @@ impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {} pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { fn handle_miri_backtrace_size( &mut self, - abi: ExternAbi, + abi: &FnAbi<'tcx, Ty<'tcx>>, link_name: Symbol, args: &[OpTy<'tcx>], dest: &MPlaceTy<'tcx>, ) -> InterpResult<'tcx> { 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()?; if flags != 0 { @@ -30,7 +31,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { fn handle_miri_get_backtrace( &mut self, - abi: ExternAbi, + abi: &FnAbi<'tcx, Ty<'tcx>>, link_name: Symbol, args: &[OpTy<'tcx>], dest: &MPlaceTy<'tcx>, @@ -71,7 +72,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // storage for pointers is allocated by miri // deallocating the slice is undefined behavior with a custom global allocator 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())?; @@ -86,7 +87,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { } // storage for pointers is allocated by the caller 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)?; @@ -136,13 +137,13 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { fn handle_miri_resolve_frame( &mut self, - abi: ExternAbi, + abi: &FnAbi<'tcx, Ty<'tcx>>, link_name: Symbol, args: &[OpTy<'tcx>], dest: &MPlaceTy<'tcx>, ) -> InterpResult<'tcx> { 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()?; @@ -207,14 +208,14 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { fn handle_miri_resolve_frame_names( &mut self, - abi: ExternAbi, + abi: &FnAbi<'tcx, Ty<'tcx>>, link_name: Symbol, args: &[OpTy<'tcx>], ) -> InterpResult<'tcx> { let this = self.eval_context_mut(); 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()?; if flags != 0 { diff --git a/src/tools/miri/src/shims/foreign_items.rs b/src/tools/miri/src/shims/foreign_items.rs index 4dc857ef30b49..8c8850ba7e0a8 100644 --- a/src/tools/miri/src/shims/foreign_items.rs +++ b/src/tools/miri/src/shims/foreign_items.rs @@ -3,14 +3,16 @@ use std::io::Write; use std::iter; use std::path::Path; -use rustc_abi::{Align, AlignFromBytesError, ExternAbi, Size}; +use rustc_abi::{Align, AlignFromBytesError, Size}; use rustc_apfloat::Float; use rustc_ast::expand::allocator::alloc_error_handler_name; use rustc_hir::def::DefKind; use rustc_hir::def_id::CrateNum; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; +use rustc_middle::ty::Ty; use rustc_middle::{mir, ty}; use rustc_span::Symbol; +use rustc_target::callconv::{Conv, FnAbi}; use self::helpers::{ToHost, ToSoft}; use super::alloc::EvalContextExt as _; @@ -39,7 +41,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { fn emulate_foreign_item( &mut self, link_name: Symbol, - abi: ExternAbi, + abi: &FnAbi<'tcx, Ty<'tcx>>, args: &[OpTy<'tcx>], dest: &MPlaceTy<'tcx>, ret: Option, @@ -106,7 +108,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { fn emulate_dyn_sym( &mut self, sym: DynSym, - abi: ExternAbi, + abi: &FnAbi<'tcx, Ty<'tcx>>, args: &[OpTy<'tcx>], dest: &MPlaceTy<'tcx>, ret: Option, @@ -218,7 +220,7 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { fn emulate_foreign_item_inner( &mut self, link_name: Symbol, - abi: ExternAbi, + abi: &FnAbi<'tcx, Ty<'tcx>>, args: &[OpTy<'tcx>], dest: &MPlaceTy<'tcx>, ) -> InterpResult<'tcx, EmulateItemResult> { @@ -235,11 +237,10 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { return interp_ok(EmulateItemResult::NeedsReturn); } } - // When adding a new shim, you should follow the following pattern: // ``` // "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)?; // this.write_scalar(result, dest)?; // } @@ -277,16 +278,16 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { match link_name.as_str() { // Miri-specific extern functions "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)?; return interp_ok(EmulateItemResult::NeedsUnwind); } "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(); } "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 (alloc_id, _, _) = this.ptr_get_alloc_id(ptr, 0).map_err_kind(|_e| { err_machine_stop!(TerminationInfo::Abort(format!( @@ -296,7 +297,7 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { this.write_scalar(Scalar::from_u64(alloc_id.0.get()), dest)?; } "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 show_unnamed = this.read_scalar(show_unnamed)?.to_bool()?; if let Some(id) = std::num::NonZero::new(id).map(AllocId) @@ -310,8 +311,7 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { "miri_pointer_name" => { // This associates a name to a tag. Very useful for debugging, and also makes // tests more strict. - let [ptr, nth_parent, name] = - this.check_shim(abi, ExternAbi::Rust, link_name, args)?; + let [ptr, nth_parent, name] = this.check_shim(abi, Conv::Rust, link_name, args)?; let ptr = this.read_pointer(ptr)?; let nth_parent = this.read_scalar(nth_parent)?.to_u8()?; let name = this.read_immediate(name)?; @@ -324,7 +324,7 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { this.give_pointer_debug_name(ptr, nth_parent, &name)?; } "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 (alloc_id, offset, _) = this.ptr_get_alloc_id(ptr, 0)?; if offset != Size::ZERO { @@ -335,8 +335,7 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { this.machine.static_roots.push(alloc_id); } "miri_host_to_target_path" => { - let [ptr, out, out_size] = - this.check_shim(abi, ExternAbi::Rust, link_name, args)?; + let [ptr, out, out_size] = this.check_shim(abi, Conv::Rust, link_name, args)?; let ptr = this.read_pointer(ptr)?; let out = this.read_pointer(out)?; let out_size = this.read_scalar(out_size)?.to_target_usize(this)?; @@ -372,7 +371,7 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { // Writes some bytes to the interpreter's stdout/stderr. See the // README for details. "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_byte_slice(&msg)?; // Note: we're ignoring errors writing to host stdout/stderr. @@ -386,7 +385,7 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { "miri_promise_symbolic_alignment" => { 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 align = this.read_target_usize(align)?; if !align.is_power_of_two() { @@ -427,13 +426,12 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { // Aborting the process. "exit" => { - let [code] = - this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let [code] = this.check_shim(abi, Conv::C, link_name, args)?; let code = this.read_scalar(code)?.to_i32()?; throw_machine_stop!(TerminationInfo::Exit { code: code.into(), leak_check: false }); } "abort" => { - let [] = this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let [] = this.check_shim(abi, Conv::C, link_name, args)?; throw_machine_stop!(TerminationInfo::Abort( "the program aborted execution".to_owned() )) @@ -441,8 +439,7 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { // Standard C allocation "malloc" => { - let [size] = - this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let [size] = this.check_shim(abi, Conv::C, link_name, args)?; let size = this.read_target_usize(size)?; if size <= this.max_size_of_val().bytes() { let res = this.malloc(size, /*zero_init:*/ false)?; @@ -456,8 +453,7 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { } } "calloc" => { - let [items, elem_size] = - this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let [items, elem_size] = this.check_shim(abi, Conv::C, link_name, args)?; let items = this.read_target_usize(items)?; let elem_size = this.read_target_usize(elem_size)?; if let Some(size) = this.compute_size_in_bytes(Size::from_bytes(elem_size), items) { @@ -472,14 +468,12 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { } } "free" => { - let [ptr] = - this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let [ptr] = this.check_shim(abi, Conv::C, link_name, args)?; let ptr = this.read_pointer(ptr)?; this.free(ptr)?; } "realloc" => { - let [old_ptr, new_size] = - this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let [old_ptr, new_size] = this.check_shim(abi, Conv::C, link_name, args)?; let old_ptr = this.read_pointer(old_ptr)?; let new_size = this.read_target_usize(new_size)?; if new_size <= this.max_size_of_val().bytes() { @@ -499,7 +493,7 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { let default = |ecx: &mut MiriInterpCx<'tcx>| { // 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. - 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 align = ecx.read_target_usize(align)?; @@ -533,7 +527,7 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { return this.emulate_allocator(|this| { // See the comment for `__rust_alloc` why `check_shim` is only called in the // 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 align = this.read_target_usize(align)?; @@ -559,7 +553,7 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { // See the comment for `__rust_alloc` why `check_shim` is only called in the // default case. 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 old_size = ecx.read_target_usize(old_size)?; let align = ecx.read_target_usize(align)?; @@ -594,7 +588,7 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { // See the comment for `__rust_alloc` why `check_shim` is only called in the // default case. 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 old_size = this.read_target_usize(old_size)?; let align = this.read_target_usize(align)?; @@ -617,8 +611,7 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { // C memory handling functions "memcmp" => { - let [left, right, n] = - this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let [left, right, n] = this.check_shim(abi, Conv::C, link_name, args)?; let left = this.read_pointer(left)?; let right = this.read_pointer(right)?; let n = Size::from_bytes(this.read_target_usize(n)?); @@ -642,8 +635,7 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { this.write_scalar(Scalar::from_i32(result), dest)?; } "memrchr" => { - let [ptr, val, num] = - this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let [ptr, val, num] = this.check_shim(abi, Conv::C, link_name, args)?; let ptr = this.read_pointer(ptr)?; let val = this.read_scalar(val)?.to_i32()?; let num = this.read_target_usize(num)?; @@ -669,8 +661,7 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { } } "memchr" => { - let [ptr, val, num] = - this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let [ptr, val, num] = this.check_shim(abi, Conv::C, link_name, args)?; let ptr = this.read_pointer(ptr)?; let val = this.read_scalar(val)?.to_i32()?; let num = this.read_target_usize(num)?; @@ -693,8 +684,7 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { } } "strlen" => { - let [ptr] = - this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let [ptr] = this.check_shim(abi, Conv::C, link_name, args)?; let ptr = this.read_pointer(ptr)?; // 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(); @@ -704,8 +694,7 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { )?; } "wcslen" => { - let [ptr] = - this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let [ptr] = this.check_shim(abi, Conv::C, link_name, args)?; let ptr = this.read_pointer(ptr)?; // 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(); @@ -715,8 +704,7 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { )?; } "memcpy" => { - let [ptr_dest, ptr_src, n] = - this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let [ptr_dest, ptr_src, n] = this.check_shim(abi, Conv::C, link_name, args)?; let ptr_dest = this.read_pointer(ptr_dest)?; let ptr_src = this.read_pointer(ptr_src)?; let n = this.read_target_usize(n)?; @@ -730,8 +718,7 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { this.write_pointer(ptr_dest, dest)?; } "strcpy" => { - let [ptr_dest, ptr_src] = - this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let [ptr_dest, ptr_src] = this.check_shim(abi, Conv::C, link_name, args)?; let ptr_dest = this.read_pointer(ptr_dest)?; let ptr_src = this.read_pointer(ptr_src)?; @@ -760,7 +747,7 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { | "expm1f" | "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()?; // Using host floats (but it's fine, these operations do not have guaranteed precision). let f_host = f.to_host(); @@ -788,7 +775,7 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { | "atan2f" | "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 f2 = this.read_scalar(f2)?.to_f32()?; // underscore case for windows, here and below @@ -817,7 +804,7 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { | "expm1" | "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()?; // Using host floats (but it's fine, these operations do not have guaranteed precision). let f_host = f.to_host(); @@ -845,7 +832,7 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { | "atan2" | "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 f2 = this.read_scalar(f2)?.to_f64()?; // underscore case for windows, here and below @@ -866,7 +853,7 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { | "ldexp" | "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. let x = this.read_scalar(x)?.to_f64()?; let exp = this.read_scalar(exp)?.to_i32()?; @@ -876,8 +863,7 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { this.write_scalar(res, dest)?; } "lgammaf_r" => { - let [x, signp] = - this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let [x, signp] = this.check_shim(abi, Conv::C, link_name, args)?; let x = this.read_scalar(x)?.to_f32()?; let signp = this.deref_pointer(signp)?; @@ -888,8 +874,7 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { this.write_scalar(res, dest)?; } "lgamma_r" => { - let [x, signp] = - this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let [x, signp] = this.check_shim(abi, Conv::C, link_name, args)?; let x = this.read_scalar(x)?.to_f64()?; let signp = this.deref_pointer(signp)?; @@ -902,8 +887,7 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { // LLVM intrinsics "llvm.prefetch" => { - let [p, rw, loc, ty] = - this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let [p, rw, loc, ty] = this.check_shim(abi, Conv::C, link_name, args)?; let _ = this.read_pointer(p)?; let rw = this.read_scalar(rw)?.to_i32()?; @@ -930,7 +914,7 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { // Used to implement the x86 `_mm{,256,512}_popcnt_epi{8,16,32,64}` and wasm // `{i,u}8x16_popcnt` functions. 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 (dest, dest_len) = this.project_to_simd(dest)?; @@ -961,7 +945,7 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { } // FIXME: Move these to an `arm` submodule. "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()?; match arg { // SY ("full system scope") @@ -974,7 +958,7 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { } } "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()?; // Note that different arguments might have different target feature requirements. match arg { diff --git a/src/tools/miri/src/shims/unix/android/foreign_items.rs b/src/tools/miri/src/shims/unix/android/foreign_items.rs index f9003885450c8..0e7cf7153f5b3 100644 --- a/src/tools/miri/src/shims/unix/android/foreign_items.rs +++ b/src/tools/miri/src/shims/unix/android/foreign_items.rs @@ -1,5 +1,6 @@ -use rustc_abi::ExternAbi; +use rustc_middle::ty::Ty; use rustc_span::Symbol; +use rustc_target::callconv::{Conv, FnAbi}; use crate::shims::unix::android::thread::prctl; use crate::shims::unix::linux_like::epoll::EvalContextExt as _; @@ -16,7 +17,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { fn emulate_foreign_item_inner( &mut self, link_name: Symbol, - abi: ExternAbi, + abi: &FnAbi<'tcx, Ty<'tcx>>, args: &[OpTy<'tcx>], dest: &MPlaceTy<'tcx>, ) -> InterpResult<'tcx, EmulateItemResult> { @@ -24,32 +25,29 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { match link_name.as_str() { // epoll, eventfd "epoll_create1" => { - let [flag] = - this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let [flag] = this.check_shim(abi, Conv::C, link_name, args)?; let result = this.epoll_create1(flag)?; this.write_scalar(result, dest)?; } "epoll_ctl" => { - let [epfd, op, fd, event] = - this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let [epfd, op, fd, event] = this.check_shim(abi, Conv::C, link_name, args)?; let result = this.epoll_ctl(epfd, op, fd, event)?; this.write_scalar(result, dest)?; } "epoll_wait" => { 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)?; } "eventfd" => { - let [val, flag] = - this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let [val, flag] = this.check_shim(abi, Conv::C, link_name, args)?; let result = this.eventfd(val, flag)?; this.write_scalar(result, dest)?; } // Miscellaneous "__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()?; this.write_scalar(errno_place.to_ref(this).to_scalar(), dest)?; } diff --git a/src/tools/miri/src/shims/unix/android/thread.rs b/src/tools/miri/src/shims/unix/android/thread.rs index f8a0b3a85a2f2..8d5d4a52b6efe 100644 --- a/src/tools/miri/src/shims/unix/android/thread.rs +++ b/src/tools/miri/src/shims/unix/android/thread.rs @@ -1,5 +1,7 @@ -use rustc_abi::{ExternAbi, Size}; +use rustc_abi::Size; +use rustc_middle::ty::Ty; use rustc_span::Symbol; +use rustc_target::callconv::{Conv, FnAbi}; use crate::helpers::check_min_arg_count; use crate::shims::unix::thread::{EvalContextExt as _, ThreadNameResult}; @@ -10,13 +12,13 @@ const TASK_COMM_LEN: usize = 16; pub fn prctl<'tcx>( ecx: &mut MiriInterpCx<'tcx>, link_name: Symbol, - abi: ExternAbi, + abi: &FnAbi<'tcx, Ty<'tcx>>, args: &[OpTy<'tcx>], dest: &MPlaceTy<'tcx>, ) -> InterpResult<'tcx> { // We do not use `check_shim` here because `prctl` is variadic. The argument // 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. let pr_set_name = 15; diff --git a/src/tools/miri/src/shims/unix/foreign_items.rs b/src/tools/miri/src/shims/unix/foreign_items.rs index 88ec32808b1c7..f47a96b10fe58 100644 --- a/src/tools/miri/src/shims/unix/foreign_items.rs +++ b/src/tools/miri/src/shims/unix/foreign_items.rs @@ -1,9 +1,11 @@ use std::ffi::OsStr; use std::str; -use rustc_abi::{ExternAbi, Size}; +use rustc_abi::Size; +use rustc_middle::ty::Ty; use rustc_middle::ty::layout::LayoutOf; use rustc_span::Symbol; +use rustc_target::callconv::{Conv, FnAbi}; use self::shims::unix::android::foreign_items as android; 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( &mut self, link_name: Symbol, - abi: ExternAbi, + abi: &FnAbi<'tcx, Ty<'tcx>>, args: &[OpTy<'tcx>], dest: &MPlaceTy<'tcx>, ) -> InterpResult<'tcx, EmulateItemResult> { @@ -111,54 +113,52 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { match link_name.as_str() { // Environment related shims "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)?; this.write_pointer(result, dest)?; } "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)?; this.write_scalar(result, dest)?; } "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()?; let result = this.setenv(name, value)?; this.write_scalar(result, dest)?; } "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)?; this.write_pointer(result, dest)?; } "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)?; this.write_scalar(result, dest)?; } "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()?; this.write_scalar(result, dest)?; } - "sysconf" => { 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)?; this.write_scalar(result, dest)?; } - // File descriptors "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 buf = this.read_pointer(buf)?; let count = this.read_target_usize(count)?; this.read(fd, buf, count, None, dest)?; } "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 buf = this.read_pointer(buf)?; 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)?; } "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 buf = this.read_pointer(buf)?; 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)?; } "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 buf = this.read_pointer(buf)?; 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)?; } "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 buf = this.read_pointer(buf)?; 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)?; } "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 buf = this.read_pointer(buf)?; 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)?; } "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)?; this.write_scalar(result, dest)?; } "fcntl" => { // `fcntl` is variadic. The argument count is checked based on the first argument // 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)?; this.write_scalar(result, dest)?; } "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 new_fd = this.dup(old_fd)?; this.write_scalar(new_fd, dest)?; } "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 new_fd = this.read_scalar(new_fd)?.to_i32()?; let result = this.dup2(old_fd, new_fd)?; this.write_scalar(result, dest)?; } "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 op = this.read_scalar(op)?.to_i32()?; let result = this.flock(fd, op)?; @@ -235,47 +235,47 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // File and file system access "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 - 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)?; this.write_scalar(result, dest)?; } "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)?; this.write_scalar(result, dest)?; } "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)?; this.write_scalar(result, dest)?; } "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)?; this.write_scalar(result, dest)?; } "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)?; this.write_scalar(result, dest)?; } "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)?; this.write_scalar(result, dest)?; } "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)?; this.write_scalar(result, dest)?; } "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)?; this.write_scalar(result, dest)?; } "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 offset = this.read_scalar(offset)?.to_i64()?; let whence = this.read_scalar(whence)?.to_i32()?; @@ -283,7 +283,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { this.write_scalar(result, dest)?; } "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 offset = this.read_scalar(offset)?.to_int(this.libc_ty_layout("off_t").size)?; let whence = this.read_scalar(whence)?.to_i32()?; @@ -292,7 +292,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { } "ftruncate64" => { 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 length = this.read_scalar(length)?.to_i64()?; let result = this.ftruncate64(fd, length.into())?; @@ -300,30 +300,30 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { } "ftruncate" => { 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 length = this.read_scalar(length)?.to_int(this.libc_ty_layout("off_t").size)?; let result = this.ftruncate64(fd, length)?; this.write_scalar(result, dest)?; } "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)?; this.write_scalar(result, dest)?; } "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)?; this.write_scalar(result, dest)?; } "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)?; this.write_scalar(Scalar::from_target_isize(result, this), dest)?; } "posix_fadvise" => { 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_target_isize(offset)?; this.read_target_isize(len)?; @@ -332,12 +332,12 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { this.write_null(dest)?; } "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)?; this.write_scalar(result, dest)?; } "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)?; this.write_scalar(result, dest)?; } @@ -345,13 +345,13 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // Unnamed sockets and pipes "socketpair" => { 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)?; this.write_scalar(result, dest)?; } "pipe" => { 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)?; this.write_scalar(result, dest)?; } @@ -364,44 +364,44 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { ); } 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))?; this.write_scalar(result, dest)?; } // Time "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)?; this.write_scalar(result, dest)?; } "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)?; this.write_pointer(result, dest)?; } "clock_gettime" => { 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)?; this.write_scalar(result, dest)?; } // Allocation "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)?; this.write_scalar(result, dest)?; } "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 ptr = this.mmap(addr, length, prot, flags, fd, offset)?; this.write_scalar(ptr, dest)?; } "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)?; this.write_scalar(result, dest)?; } @@ -415,7 +415,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { ); } 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 nmemb = this.read_target_usize(nmemb)?; 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. // (MSVC explicitly does not support this.) 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)?; this.write_pointer(res, dest)?; } // Dynamic symbol loading "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)?; let symbol = this.read_pointer(symbol)?; let name = this.read_c_str(symbol)?; @@ -460,7 +460,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // Thread-local storage "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 dtor = this.read_pointer(dtor)?; @@ -488,21 +488,21 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { this.write_null(dest)?; } "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)?; this.machine.tls.delete_tls_key(key)?; // Return success (0) this.write_null(dest)?; } "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 active_thread = this.active_thread(); let ptr = this.machine.tls.load_tls(key, active_thread, this)?; this.write_scalar(ptr, dest)?; } "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 active_thread = this.active_thread(); let new_data = this.read_scalar(new_ptr)?; @@ -514,151 +514,151 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // Synchronization primitives "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.write_null(dest)?; } "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)?; this.write_scalar(result, dest)?; } "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.write_null(dest)?; } "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.write_null(dest)?; } "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)?; } "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)?; this.write_scalar(result, dest)?; } "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)?; this.write_scalar(result, dest)?; } "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.write_int(0, dest)?; } "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)?; } "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)?; this.write_scalar(result, dest)?; } "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)?; } "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)?; this.write_scalar(result, dest)?; } "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.write_null(dest)?; } "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.write_null(dest)?; } "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.write_null(dest)?; } "pthread_condattr_setclock" => { 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)?; this.write_scalar(result, dest)?; } "pthread_condattr_getclock" => { 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.write_null(dest)?; } "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.write_null(dest)?; } "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.write_null(dest)?; } "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.write_null(dest)?; } "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.write_null(dest)?; } "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)?; } "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)?; } "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.write_null(dest)?; } // Threading "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.write_null(dest)?; } "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)?; this.write_scalar(res, dest)?; } "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)?; this.write_scalar(res, dest)?; } "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()?; this.write_scalar(res, dest)?; } "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.write_null(dest)?; } "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)?; this.write_scalar(result, dest)?; } @@ -672,7 +672,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { } 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 cpusetsize = this.read_target_usize(cpusetsize)?; let mask = this.read_pointer(mask)?; @@ -712,7 +712,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { } 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 cpusetsize = this.read_target_usize(cpusetsize)?; let mask = this.read_pointer(mask)?; @@ -748,12 +748,12 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // Miscellaneous "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)?; this.write_scalar(result, dest)?; } "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(parent)?; this.read_pointer(child)?; @@ -771,7 +771,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { } 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 bufsize = this.read_target_usize(bufsize)?; @@ -790,7 +790,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { "strerror_r" => { 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)?; this.write_scalar(result, dest)?; } @@ -805,7 +805,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { ); } 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 len = this.read_target_usize(len)?; let _flags = this.read_scalar(flags)?.to_i32()?; @@ -822,7 +822,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { 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 len = this.read_target_usize(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. - 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)?; return interp_ok(EmulateItemResult::NeedsUnwind); } "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. 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. "pthread_attr_getguardsize" 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_layout = this.libc_ty_layout("size_t"); 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_destroy" 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)?; } | "pthread_attr_setstacksize" 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)?; } @@ -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. // Hence we can mostly ignore the input `attr_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 addr_place = this.deref_pointer(addr_place)?; let size_place = this.deref_pointer(size_place)?; @@ -909,13 +909,13 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { | "signal" | "sigaltstack" 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)?; } | "sigaction" | "mprotect" 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)?; } @@ -923,7 +923,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { if this.frame_in_std() => { // getpwuid_r is the standard name, __posix_getpwuid_r is used on solarish 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`")?; let uid = this.read_scalar(uid)?.to_u32()?; diff --git a/src/tools/miri/src/shims/unix/freebsd/foreign_items.rs b/src/tools/miri/src/shims/unix/freebsd/foreign_items.rs index 0c9bc005ece47..5381234e28ca7 100644 --- a/src/tools/miri/src/shims/unix/freebsd/foreign_items.rs +++ b/src/tools/miri/src/shims/unix/freebsd/foreign_items.rs @@ -1,5 +1,6 @@ -use rustc_abi::ExternAbi; +use rustc_middle::ty::Ty; use rustc_span::Symbol; +use rustc_target::callconv::{Conv, FnAbi}; use crate::shims::unix::*; use crate::*; @@ -13,7 +14,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { fn emulate_foreign_item_inner( &mut self, link_name: Symbol, - abi: ExternAbi, + abi: &FnAbi<'tcx, Ty<'tcx>>, args: &[OpTy<'tcx>], dest: &MPlaceTy<'tcx>, ) -> InterpResult<'tcx, EmulateItemResult> { @@ -21,8 +22,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { match link_name.as_str() { // Threading "pthread_set_name_np" => { - let [thread, name] = - this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let [thread, name] = this.check_shim(abi, Conv::C, link_name, args)?; let max_len = usize::MAX; // FreeBSD does not seem to have a limit. // FreeBSD's pthread_set_name_np does not return anything. this.pthread_setname_np( @@ -33,8 +33,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { )?; } "pthread_get_name_np" => { - let [thread, name, len] = - this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let [thread, name, len] = this.check_shim(abi, Conv::C, link_name, args)?; // FreeBSD's pthread_get_name_np does not return anything // and uses strlcpy, which truncates the resulting value, // but always adds a null terminator (except for zero-sized buffers). @@ -51,33 +50,29 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // For those, we both intercept `func` and `call@FBSD_1.0` symbols cases // since freebsd 12 the former form can be expected. "stat" | "stat@FBSD_1.0" => { - let [path, buf] = - this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let [path, buf] = this.check_shim(abi, Conv::C, link_name, args)?; let result = this.macos_fbsd_solaris_stat(path, buf)?; this.write_scalar(result, dest)?; } "lstat" | "lstat@FBSD_1.0" => { - let [path, buf] = - this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let [path, buf] = this.check_shim(abi, Conv::C, link_name, args)?; let result = this.macos_fbsd_solaris_lstat(path, buf)?; this.write_scalar(result, dest)?; } "fstat" | "fstat@FBSD_1.0" => { - let [fd, buf] = - this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let [fd, buf] = this.check_shim(abi, Conv::C, link_name, args)?; let result = this.macos_fbsd_solaris_fstat(fd, buf)?; this.write_scalar(result, dest)?; } "readdir_r" | "readdir_r@FBSD_1.0" => { - let [dirp, entry, result] = - this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let [dirp, entry, result] = this.check_shim(abi, Conv::C, link_name, args)?; let result = this.macos_fbsd_readdir_r(dirp, entry, result)?; this.write_scalar(result, dest)?; } // Miscellaneous "__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()?; this.write_scalar(errno_place.to_ref(this).to_scalar(), dest)?; } @@ -85,8 +80,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // Incomplete shims that we "stub out" just to get pre-main initialization code to work. // These shims are enabled only when the caller is in the standard library. "pthread_attr_get_np" if this.frame_in_std() => { - let [_thread, _attr] = - this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let [_thread, _attr] = this.check_shim(abi, Conv::C, link_name, args)?; this.write_null(dest)?; } diff --git a/src/tools/miri/src/shims/unix/linux/foreign_items.rs b/src/tools/miri/src/shims/unix/linux/foreign_items.rs index 6d0a2143fe36b..10af245dcc087 100644 --- a/src/tools/miri/src/shims/unix/linux/foreign_items.rs +++ b/src/tools/miri/src/shims/unix/linux/foreign_items.rs @@ -1,5 +1,6 @@ -use rustc_abi::ExternAbi; +use rustc_middle::ty::Ty; use rustc_span::Symbol; +use rustc_target::callconv::{Conv, FnAbi}; use self::shims::unix::linux::mem::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( &mut self, link_name: Symbol, - abi: ExternAbi, + abi: &FnAbi<'tcx, Ty<'tcx>>, args: &[OpTy<'tcx>], dest: &MPlaceTy<'tcx>, ) -> InterpResult<'tcx, EmulateItemResult> { @@ -35,53 +36,47 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { match link_name.as_str() { // File related shims "readdir64" => { - 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.linux_solarish_readdir64("dirent64", dirp)?; this.write_scalar(result, dest)?; } "sync_file_range" => { - let [fd, offset, nbytes, flags] = - this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let [fd, offset, nbytes, flags] = this.check_shim(abi, Conv::C, link_name, args)?; let result = this.sync_file_range(fd, offset, nbytes, flags)?; this.write_scalar(result, dest)?; } "statx" => { 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)?; this.write_scalar(result, dest)?; } // epoll, eventfd "epoll_create1" => { - let [flag] = - this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let [flag] = this.check_shim(abi, Conv::C, link_name, args)?; let result = this.epoll_create1(flag)?; this.write_scalar(result, dest)?; } "epoll_ctl" => { - let [epfd, op, fd, event] = - this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let [epfd, op, fd, event] = this.check_shim(abi, Conv::C, link_name, args)?; let result = this.epoll_ctl(epfd, op, fd, event)?; this.write_scalar(result, dest)?; } "epoll_wait" => { 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)?; } "eventfd" => { - let [val, flag] = - this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let [val, flag] = this.check_shim(abi, Conv::C, link_name, args)?; let result = this.eventfd(val, flag)?; this.write_scalar(result, dest)?; } // Threading "pthread_setname_np" => { - let [thread, name] = - this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let [thread, name] = this.check_shim(abi, Conv::C, link_name, args)?; let res = match this.pthread_setname_np( this.read_scalar(thread)?, this.read_scalar(name)?, @@ -96,8 +91,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { this.write_scalar(res, dest)?; } "pthread_getname_np" => { - let [thread, name, len] = - this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let [thread, name, len] = this.check_shim(abi, Conv::C, link_name, args)?; // The function's behavior isn't portable between platforms. // In case of glibc, the length of the output buffer must // be not shorter than TASK_COMM_LEN. @@ -120,7 +114,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { this.write_scalar(res, dest)?; } "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()?; this.write_scalar(result, dest)?; } @@ -133,35 +127,34 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // Miscellaneous "mmap64" => { 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 ptr = this.mmap(addr, length, prot, flags, fd, offset.into())?; this.write_scalar(ptr, dest)?; } "mremap" => { 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)?; this.write_scalar(ptr, dest)?; } "__xpg_strerror_r" => { - let [errnum, buf, buflen] = - this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let [errnum, buf, buflen] = this.check_shim(abi, Conv::C, link_name, args)?; let result = this.strerror_r(errnum, buf, buflen)?; this.write_scalar(result, dest)?; } "__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()?; this.write_scalar(errno_place.to_ref(this).to_scalar(), dest)?; } "__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)?; } "__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)?; } @@ -169,8 +162,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // Incomplete shims that we "stub out" just to get pre-main initialization code to work. // These shims are enabled only when the caller is in the standard library. "pthread_getattr_np" if this.frame_in_std() => { - let [_thread, _attr] = - this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let [_thread, _attr] = this.check_shim(abi, Conv::C, link_name, args)?; this.write_null(dest)?; } diff --git a/src/tools/miri/src/shims/unix/linux_like/syscall.rs b/src/tools/miri/src/shims/unix/linux_like/syscall.rs index e9a32a263263f..5fb262e176f0b 100644 --- a/src/tools/miri/src/shims/unix/linux_like/syscall.rs +++ b/src/tools/miri/src/shims/unix/linux_like/syscall.rs @@ -1,5 +1,6 @@ -use rustc_abi::ExternAbi; +use rustc_middle::ty::Ty; use rustc_span::Symbol; +use rustc_target::callconv::{Conv, FnAbi}; use crate::helpers::check_min_arg_count; use crate::shims::unix::linux_like::eventfd::EvalContextExt as _; @@ -9,13 +10,13 @@ use crate::*; pub fn syscall<'tcx>( ecx: &mut MiriInterpCx<'tcx>, link_name: Symbol, - abi: ExternAbi, + abi: &FnAbi<'tcx, Ty<'tcx>>, args: &[OpTy<'tcx>], dest: &MPlaceTy<'tcx>, ) -> InterpResult<'tcx> { // We do not use `check_shim` here because `syscall` is variadic. The argument // 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, // 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 diff --git a/src/tools/miri/src/shims/unix/macos/foreign_items.rs b/src/tools/miri/src/shims/unix/macos/foreign_items.rs index 103bea0862086..aa291639a6db6 100644 --- a/src/tools/miri/src/shims/unix/macos/foreign_items.rs +++ b/src/tools/miri/src/shims/unix/macos/foreign_items.rs @@ -1,5 +1,6 @@ -use rustc_abi::ExternAbi; +use rustc_middle::ty::Ty; use rustc_span::Symbol; +use rustc_target::callconv::{Conv, FnAbi}; use super::sync::EvalContextExt as _; use crate::shims::unix::*; @@ -14,7 +15,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { fn emulate_foreign_item_inner( &mut self, link_name: Symbol, - abi: ExternAbi, + abi: &FnAbi<'tcx, Ty<'tcx>>, args: &[OpTy<'tcx>], dest: &MPlaceTy<'tcx>, ) -> InterpResult<'tcx, EmulateItemResult> { @@ -25,66 +26,58 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { match link_name.as_str() { // errno "__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()?; this.write_scalar(errno_place.to_ref(this).to_scalar(), dest)?; } // File related shims "close$NOCANCEL" => { - let [result] = - this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let [result] = this.check_shim(abi, Conv::C, link_name, args)?; let result = this.close(result)?; this.write_scalar(result, dest)?; } "stat" | "stat64" | "stat$INODE64" => { - let [path, buf] = - this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let [path, buf] = this.check_shim(abi, Conv::C, link_name, args)?; let result = this.macos_fbsd_solaris_stat(path, buf)?; this.write_scalar(result, dest)?; } "lstat" | "lstat64" | "lstat$INODE64" => { - let [path, buf] = - this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let [path, buf] = this.check_shim(abi, Conv::C, link_name, args)?; let result = this.macos_fbsd_solaris_lstat(path, buf)?; this.write_scalar(result, dest)?; } "fstat" | "fstat64" | "fstat$INODE64" => { - let [fd, buf] = - this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let [fd, buf] = this.check_shim(abi, Conv::C, link_name, args)?; let result = this.macos_fbsd_solaris_fstat(fd, buf)?; this.write_scalar(result, dest)?; } "opendir$INODE64" => { - 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)?; this.write_scalar(result, dest)?; } "readdir_r" | "readdir_r$INODE64" => { - let [dirp, entry, result] = - this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let [dirp, entry, result] = this.check_shim(abi, Conv::C, link_name, args)?; let result = this.macos_fbsd_readdir_r(dirp, entry, result)?; this.write_scalar(result, dest)?; } "realpath$DARWIN_EXTSN" => { - 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)?; this.write_scalar(result, dest)?; } // Environment related shims "_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(); this.write_pointer(environ, dest)?; } // Random data generation "CCRandomGenerateBytes" => { - let [bytes, count] = - this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let [bytes, count] = this.check_shim(abi, Conv::C, link_name, args)?; let bytes = this.read_pointer(bytes)?; let count = this.read_target_usize(count)?; let success = this.eval_libc_i32("kCCSuccess"); @@ -94,30 +87,28 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // Time related shims "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()?; this.write_scalar(result, dest)?; } "mach_timebase_info" => { - let [info] = - this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let [info] = this.check_shim(abi, Conv::C, link_name, args)?; let result = this.mach_timebase_info(info)?; this.write_scalar(result, dest)?; } // Access to command-line arguments "_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)?; } "_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)?; } "_NSGetExecutablePath" => { - let [buf, bufsize] = - this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let [buf, bufsize] = this.check_shim(abi, Conv::C, link_name, args)?; this.check_no_isolation("`_NSGetExecutablePath`")?; let buf_ptr = this.read_pointer(buf)?; @@ -142,8 +133,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // Thread-local storage "_tlv_atexit" => { - let [dtor, data] = - this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let [dtor, data] = this.check_shim(abi, Conv::C, link_name, args)?; let dtor = this.read_pointer(dtor)?; let dtor = this.get_ptr_fn(dtor)?.as_instance()?; let data = this.read_scalar(data)?; @@ -153,15 +143,13 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // Querying system information "pthread_get_stackaddr_np" => { - let [thread] = - this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let [thread] = this.check_shim(abi, Conv::C, link_name, args)?; this.read_target_usize(thread)?; let stack_addr = Scalar::from_uint(this.machine.stack_addr, this.pointer_size()); this.write_scalar(stack_addr, dest)?; } "pthread_get_stacksize_np" => { - let [thread] = - this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let [thread] = this.check_shim(abi, Conv::C, link_name, args)?; this.read_target_usize(thread)?; let stack_size = Scalar::from_uint(this.machine.stack_size, this.pointer_size()); this.write_scalar(stack_size, dest)?; @@ -169,8 +157,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // Threading "pthread_setname_np" => { - let [name] = - this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let [name] = this.check_shim(abi, Conv::C, link_name, args)?; // 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, @@ -197,8 +184,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { this.write_scalar(res, dest)?; } "pthread_getname_np" => { - let [thread, name, len] = - this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let [thread, name, len] = this.check_shim(abi, Conv::C, link_name, args)?; // The function's behavior isn't portable between platforms. // In case of macOS, a truncated name (due to a too small buffer) @@ -223,28 +209,23 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { } "os_unfair_lock_lock" => { - let [lock_op] = - this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let [lock_op] = this.check_shim(abi, Conv::C, link_name, args)?; this.os_unfair_lock_lock(lock_op)?; } "os_unfair_lock_trylock" => { - let [lock_op] = - this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let [lock_op] = this.check_shim(abi, Conv::C, link_name, args)?; this.os_unfair_lock_trylock(lock_op, dest)?; } "os_unfair_lock_unlock" => { - let [lock_op] = - this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let [lock_op] = this.check_shim(abi, Conv::C, link_name, args)?; this.os_unfair_lock_unlock(lock_op)?; } "os_unfair_lock_assert_owner" => { - let [lock_op] = - this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let [lock_op] = this.check_shim(abi, Conv::C, link_name, args)?; this.os_unfair_lock_assert_owner(lock_op)?; } "os_unfair_lock_assert_not_owner" => { - let [lock_op] = - this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let [lock_op] = this.check_shim(abi, Conv::C, link_name, args)?; this.os_unfair_lock_assert_not_owner(lock_op)?; } diff --git a/src/tools/miri/src/shims/unix/solarish/foreign_items.rs b/src/tools/miri/src/shims/unix/solarish/foreign_items.rs index faf280ad8815d..c99e8ae7c6ef0 100644 --- a/src/tools/miri/src/shims/unix/solarish/foreign_items.rs +++ b/src/tools/miri/src/shims/unix/solarish/foreign_items.rs @@ -1,5 +1,6 @@ -use rustc_abi::ExternAbi; +use rustc_middle::ty::Ty; use rustc_span::Symbol; +use rustc_target::callconv::{Conv, FnAbi}; use crate::shims::unix::foreign_items::EvalContextExt as _; use crate::shims::unix::*; @@ -14,7 +15,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { fn emulate_foreign_item_inner( &mut self, link_name: Symbol, - abi: ExternAbi, + abi: &FnAbi<'tcx, Ty<'tcx>>, args: &[OpTy<'tcx>], dest: &MPlaceTy<'tcx>, ) -> InterpResult<'tcx, EmulateItemResult> { @@ -22,8 +23,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { match link_name.as_str() { // Threading "pthread_setname_np" => { - let [thread, name] = - this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let [thread, name] = this.check_shim(abi, Conv::C, link_name, args)?; // 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 let max_len = 32; @@ -41,8 +41,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { this.write_scalar(res, dest)?; } "pthread_getname_np" => { - let [thread, name, len] = - this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let [thread, name, len] = this.check_shim(abi, Conv::C, link_name, args)?; // See https://illumos.org/man/3C/pthread_getname_np for the error codes. let res = match this.pthread_getname_np( this.read_scalar(thread)?, @@ -59,40 +58,35 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // File related shims "stat" | "stat64" => { - let [path, buf] = - this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let [path, buf] = this.check_shim(abi, Conv::C, link_name, args)?; let result = this.macos_fbsd_solaris_stat(path, buf)?; this.write_scalar(result, dest)?; } "lstat" | "lstat64" => { - let [path, buf] = - this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let [path, buf] = this.check_shim(abi, Conv::C, link_name, args)?; let result = this.macos_fbsd_solaris_lstat(path, buf)?; this.write_scalar(result, dest)?; } "fstat" | "fstat64" => { - let [fd, buf] = - this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let [fd, buf] = this.check_shim(abi, Conv::C, link_name, args)?; let result = this.macos_fbsd_solaris_fstat(fd, buf)?; this.write_scalar(result, dest)?; } "readdir" => { - 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.linux_solarish_readdir64("dirent", dirp)?; this.write_scalar(result, dest)?; } // Miscellaneous "___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()?; this.write_scalar(errno_place.to_ref(this).to_scalar(), dest)?; } "stack_getbounds" => { - let [stack] = - this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let [stack] = this.check_shim(abi, Conv::C, link_name, args)?; let stack = this.deref_pointer_as(stack, this.libc_ty_layout("stack_t"))?; this.write_int_fields_named( @@ -110,8 +104,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { } "pset_info" => { - let [pset, tpe, cpus, list] = - this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let [pset, tpe, cpus, list] = this.check_shim(abi, Conv::C, link_name, args)?; // We do not need to handle the current process cpu mask, available_parallelism // implementation pass null anyway. We only care for the number of // cpus. @@ -140,8 +133,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { } "__sysconf_xpg7" => { - let [val] = - this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let [val] = this.check_shim(abi, Conv::C, link_name, args)?; let result = this.sysconf(val)?; this.write_scalar(result, dest)?; } diff --git a/src/tools/miri/src/shims/wasi/foreign_items.rs b/src/tools/miri/src/shims/wasi/foreign_items.rs index 2c349203d465f..90de62b9e574a 100644 --- a/src/tools/miri/src/shims/wasi/foreign_items.rs +++ b/src/tools/miri/src/shims/wasi/foreign_items.rs @@ -1,5 +1,6 @@ -use rustc_abi::ExternAbi; +use rustc_middle::ty::Ty; use rustc_span::Symbol; +use rustc_target::callconv::{Conv, FnAbi}; use crate::shims::alloc::EvalContextExt as _; use crate::*; @@ -13,7 +14,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { fn emulate_foreign_item_inner( &mut self, link_name: Symbol, - abi: ExternAbi, + abi: &FnAbi<'tcx, Ty<'tcx>>, args: &[OpTy<'tcx>], dest: &MPlaceTy<'tcx>, ) -> InterpResult<'tcx, EmulateItemResult> { @@ -21,14 +22,12 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { match link_name.as_str() { // Allocation "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)?; this.write_scalar(result, dest)?; } "aligned_alloc" => { - let [align, size] = - this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let [align, size] = this.check_shim(abi, Conv::C, link_name, args)?; let res = this.aligned_alloc(align, size)?; this.write_pointer(res, dest)?; } diff --git a/src/tools/miri/src/shims/windows/foreign_items.rs b/src/tools/miri/src/shims/windows/foreign_items.rs index d6a180451d7ad..fe4d2158ff956 100644 --- a/src/tools/miri/src/shims/windows/foreign_items.rs +++ b/src/tools/miri/src/shims/windows/foreign_items.rs @@ -2,8 +2,10 @@ use std::ffi::OsStr; use std::path::{self, Path, PathBuf}; 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_target::callconv::{Conv, FnAbi}; use self::shims::windows::handle::{Handle, PseudoHandle}; 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( &mut self, link_name: Symbol, - abi: ExternAbi, + abi: &FnAbi<'tcx, Ty<'tcx>>, args: &[OpTy<'tcx>], dest: &MPlaceTy<'tcx>, ) -> InterpResult<'tcx, EmulateItemResult> { 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. // Windows API stubs. @@ -100,50 +108,42 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { match link_name.as_str() { // Environment related shims "GetEnvironmentVariableW" => { - let [name, buf, size] = - this.check_shim(abi, ExternAbi::System { unwind: false }, link_name, args)?; + let [name, buf, size] = this.check_shim(abi, sys_conv, link_name, args)?; let result = this.GetEnvironmentVariableW(name, buf, size)?; this.write_scalar(result, dest)?; } "SetEnvironmentVariableW" => { - let [name, value] = - this.check_shim(abi, ExternAbi::System { unwind: false }, link_name, args)?; + let [name, value] = this.check_shim(abi, sys_conv, link_name, args)?; let result = this.SetEnvironmentVariableW(name, value)?; this.write_scalar(result, dest)?; } "GetEnvironmentStringsW" => { - let [] = - this.check_shim(abi, ExternAbi::System { unwind: false }, link_name, args)?; + let [] = this.check_shim(abi, sys_conv, link_name, args)?; let result = this.GetEnvironmentStringsW()?; this.write_pointer(result, dest)?; } "FreeEnvironmentStringsW" => { - let [env_block] = - this.check_shim(abi, ExternAbi::System { unwind: false }, link_name, args)?; + let [env_block] = this.check_shim(abi, sys_conv, link_name, args)?; let result = this.FreeEnvironmentStringsW(env_block)?; this.write_scalar(result, dest)?; } "GetCurrentDirectoryW" => { - let [size, buf] = - this.check_shim(abi, ExternAbi::System { unwind: false }, link_name, args)?; + let [size, buf] = this.check_shim(abi, sys_conv, link_name, args)?; let result = this.GetCurrentDirectoryW(size, buf)?; this.write_scalar(result, dest)?; } "SetCurrentDirectoryW" => { - let [path] = - this.check_shim(abi, ExternAbi::System { unwind: false }, link_name, args)?; + let [path] = this.check_shim(abi, sys_conv, link_name, args)?; let result = this.SetCurrentDirectoryW(path)?; this.write_scalar(result, dest)?; } "GetUserProfileDirectoryW" => { - let [token, buf, size] = - this.check_shim(abi, ExternAbi::System { unwind: false }, link_name, args)?; + let [token, buf, size] = this.check_shim(abi, sys_conv, link_name, args)?; let result = this.GetUserProfileDirectoryW(token, buf, size)?; this.write_scalar(result, dest)?; } "GetCurrentProcessId" => { - let [] = - this.check_shim(abi, ExternAbi::System { unwind: false }, link_name, args)?; + let [] = this.check_shim(abi, sys_conv, link_name, args)?; let result = this.GetCurrentProcessId()?; this.write_scalar(result, dest)?; } @@ -166,7 +166,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { n, byte_offset, _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 buf = this.read_pointer(buf)?; let n = this.read_scalar(n)?.to_u32()?; @@ -218,7 +218,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { } "GetFullPathNameW" => { 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`")?; let filename = this.read_pointer(filename)?; @@ -249,8 +249,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // Allocation "HeapAlloc" => { - let [handle, flags, size] = - this.check_shim(abi, ExternAbi::System { unwind: false }, link_name, args)?; + let [handle, flags, size] = this.check_shim(abi, sys_conv, link_name, args)?; this.read_target_isize(handle)?; let flags = this.read_scalar(flags)?.to_u32()?; let size = this.read_target_usize(size)?; @@ -273,8 +272,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { this.write_pointer(ptr, dest)?; } "HeapFree" => { - let [handle, flags, ptr] = - this.check_shim(abi, ExternAbi::System { unwind: false }, link_name, args)?; + let [handle, flags, ptr] = this.check_shim(abi, sys_conv, link_name, args)?; this.read_target_isize(handle)?; this.read_scalar(flags)?.to_u32()?; let ptr = this.read_pointer(ptr)?; @@ -287,7 +285,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { } "HeapReAlloc" => { 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_scalar(flags)?.to_u32()?; let old_ptr = this.read_pointer(old_ptr)?; @@ -306,8 +304,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { this.write_pointer(new_ptr, dest)?; } "LocalFree" => { - let [ptr] = - this.check_shim(abi, ExternAbi::System { unwind: false }, link_name, args)?; + let [ptr] = this.check_shim(abi, sys_conv, link_name, args)?; let ptr = this.read_pointer(ptr)?; // "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) @@ -319,14 +316,12 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // errno "SetLastError" => { - let [error] = - this.check_shim(abi, ExternAbi::System { unwind: false }, link_name, args)?; + let [error] = this.check_shim(abi, sys_conv, link_name, args)?; let error = this.read_scalar(error)?; this.set_last_error(error)?; } "GetLastError" => { - let [] = - this.check_shim(abi, ExternAbi::System { unwind: false }, link_name, args)?; + let [] = this.check_shim(abi, sys_conv, link_name, args)?; let last_error = this.get_last_error()?; this.write_scalar(last_error, dest)?; } @@ -334,8 +329,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // Querying system information "GetSystemInfo" => { // Also called from `page_size` crate. - let [system_info] = - this.check_shim(abi, ExternAbi::System { unwind: false }, link_name, args)?; + let [system_info] = this.check_shim(abi, sys_conv, link_name, args)?; let system_info = this.deref_pointer_as(system_info, this.windows_ty_layout("SYSTEM_INFO"))?; // Initialize with `0`. @@ -358,22 +352,19 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // This just creates a key; Windows does not natively support TLS destructors. // Create key and return it. - let [] = - this.check_shim(abi, ExternAbi::System { unwind: false }, link_name, args)?; + let [] = this.check_shim(abi, sys_conv, link_name, args)?; let key = this.machine.tls.create_tls_key(None, dest.layout.size)?; this.write_scalar(Scalar::from_uint(key, dest.layout.size), dest)?; } "TlsGetValue" => { - let [key] = - this.check_shim(abi, ExternAbi::System { unwind: false }, link_name, args)?; + let [key] = this.check_shim(abi, sys_conv, link_name, args)?; let key = u128::from(this.read_scalar(key)?.to_u32()?); let active_thread = this.active_thread(); let ptr = this.machine.tls.load_tls(key, active_thread, this)?; this.write_scalar(ptr, dest)?; } "TlsSetValue" => { - let [key, new_ptr] = - this.check_shim(abi, ExternAbi::System { unwind: false }, link_name, args)?; + let [key, new_ptr] = this.check_shim(abi, sys_conv, link_name, args)?; let key = u128::from(this.read_scalar(key)?.to_u32()?); let active_thread = this.active_thread(); let new_data = this.read_scalar(new_ptr)?; @@ -383,8 +374,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { this.write_int(1, dest)?; } "TlsFree" => { - let [key] = - this.check_shim(abi, ExternAbi::System { unwind: false }, link_name, args)?; + let [key] = this.check_shim(abi, sys_conv, link_name, args)?; let key = u128::from(this.read_scalar(key)?.to_u32()?); this.machine.tls.delete_tls_key(key)?; @@ -394,8 +384,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // Access to command-line arguments "GetCommandLineW" => { - let [] = - this.check_shim(abi, ExternAbi::System { unwind: false }, link_name, args)?; + let [] = this.check_shim(abi, sys_conv, link_name, args)?; this.write_pointer( this.machine.cmd_line.expect("machine must be initialized"), dest, @@ -405,33 +394,29 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // Time related shims "GetSystemTimeAsFileTime" | "GetSystemTimePreciseAsFileTime" => { #[allow(non_snake_case)] - let [LPFILETIME] = - this.check_shim(abi, ExternAbi::System { unwind: false }, link_name, args)?; + let [LPFILETIME] = this.check_shim(abi, sys_conv, link_name, args)?; this.GetSystemTimeAsFileTime(link_name.as_str(), LPFILETIME)?; } "QueryPerformanceCounter" => { #[allow(non_snake_case)] - let [lpPerformanceCount] = - this.check_shim(abi, ExternAbi::System { unwind: false }, link_name, args)?; + let [lpPerformanceCount] = this.check_shim(abi, sys_conv, link_name, args)?; let result = this.QueryPerformanceCounter(lpPerformanceCount)?; this.write_scalar(result, dest)?; } "QueryPerformanceFrequency" => { #[allow(non_snake_case)] - let [lpFrequency] = - this.check_shim(abi, ExternAbi::System { unwind: false }, link_name, args)?; + let [lpFrequency] = this.check_shim(abi, sys_conv, link_name, args)?; let result = this.QueryPerformanceFrequency(lpFrequency)?; this.write_scalar(result, dest)?; } "Sleep" => { - let [timeout] = - this.check_shim(abi, ExternAbi::System { unwind: false }, link_name, args)?; + let [timeout] = this.check_shim(abi, sys_conv, link_name, args)?; this.Sleep(timeout)?; } "CreateWaitableTimerExW" => { 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(name)?; this.read_scalar(flags)?.to_u32()?; @@ -445,30 +430,27 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // Synchronization primitives "InitOnceBeginInitialize" => { 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)?; } "InitOnceComplete" => { - let [ptr, flags, context] = - this.check_shim(abi, ExternAbi::System { unwind: false }, link_name, args)?; + let [ptr, flags, context] = this.check_shim(abi, sys_conv, link_name, args)?; let result = this.InitOnceComplete(ptr, flags, context)?; this.write_scalar(result, dest)?; } "WaitOnAddress" => { 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)?; } "WakeByAddressSingle" => { - let [ptr_op] = - this.check_shim(abi, ExternAbi::System { unwind: false }, link_name, args)?; + let [ptr_op] = this.check_shim(abi, sys_conv, link_name, args)?; this.WakeByAddressSingle(ptr_op)?; } "WakeByAddressAll" => { - let [ptr_op] = - this.check_shim(abi, ExternAbi::System { unwind: false }, link_name, args)?; + let [ptr_op] = this.check_shim(abi, sys_conv, link_name, args)?; this.WakeByAddressAll(ptr_op)?; } @@ -476,8 +458,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // Dynamic symbol loading "GetProcAddress" => { #[allow(non_snake_case)] - let [hModule, lpProcName] = - this.check_shim(abi, ExternAbi::System { unwind: false }, link_name, args)?; + let [hModule, lpProcName] = this.check_shim(abi, sys_conv, link_name, args)?; this.read_target_isize(hModule)?; let name = this.read_c_str(this.read_pointer(lpProcName)?)?; if let Ok(name) = str::from_utf8(name) @@ -493,7 +474,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // Threading "CreateThread" => { 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 = this.CreateThread(security, stacksize, start, arg, flags, thread)?; @@ -501,15 +482,13 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { this.write_scalar(Handle::Thread(thread_id).to_scalar(this), dest)?; } "WaitForSingleObject" => { - let [handle, timeout] = - this.check_shim(abi, ExternAbi::System { unwind: false }, link_name, args)?; + let [handle, timeout] = this.check_shim(abi, sys_conv, link_name, args)?; let ret = this.WaitForSingleObject(handle, timeout)?; this.write_scalar(ret, dest)?; } "GetCurrentThread" => { - let [] = - this.check_shim(abi, ExternAbi::System { unwind: false }, link_name, args)?; + let [] = this.check_shim(abi, sys_conv, link_name, args)?; this.write_scalar( Handle::Pseudo(PseudoHandle::CurrentThread).to_scalar(this), @@ -517,8 +496,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { )?; } "SetThreadDescription" => { - let [handle, name] = - this.check_shim(abi, ExternAbi::System { unwind: false }, link_name, args)?; + let [handle, name] = this.check_shim(abi, sys_conv, link_name, args)?; let handle = this.read_scalar(handle)?; let name = this.read_wide_str(this.read_pointer(name)?)?; @@ -542,8 +520,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { this.write_scalar(res, dest)?; } "GetThreadDescription" => { - let [handle, name_ptr] = - this.check_shim(abi, ExternAbi::System { unwind: false }, link_name, args)?; + let [handle, name_ptr] = this.check_shim(abi, sys_conv, link_name, args)?; 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 @@ -574,16 +551,14 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // Miscellaneous "ExitProcess" => { - let [code] = - this.check_shim(abi, ExternAbi::System { unwind: false }, link_name, args)?; + let [code] = this.check_shim(abi, sys_conv, link_name, args)?; let code = this.read_scalar(code)?.to_u32()?; throw_machine_stop!(TerminationInfo::Exit { code: code.into(), leak_check: false }); } "SystemFunction036" => { // used by getrandom 0.1 // This is really 'RtlGenRandom'. - let [ptr, len] = - this.check_shim(abi, ExternAbi::System { unwind: false }, link_name, args)?; + let [ptr, len] = this.check_shim(abi, sys_conv, link_name, args)?; let ptr = this.read_pointer(ptr)?; let len = this.read_scalar(len)?.to_u32()?; this.gen_random(ptr, len.into())?; @@ -591,8 +566,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { } "ProcessPrng" => { // used by `std` - let [ptr, len] = - this.check_shim(abi, ExternAbi::System { unwind: false }, link_name, args)?; + let [ptr, len] = this.check_shim(abi, sys_conv, link_name, args)?; let ptr = this.read_pointer(ptr)?; let len = this.read_target_usize(len)?; this.gen_random(ptr, len)?; @@ -601,7 +575,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { "BCryptGenRandom" => { // used by getrandom 0.2 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 = algorithm.to_target_usize(this)?; let ptr = this.read_pointer(ptr)?; @@ -635,8 +609,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { } "GetConsoleScreenBufferInfo" => { // `term` needs this, so we fake it. - let [console, buffer_info] = - this.check_shim(abi, ExternAbi::System { unwind: false }, link_name, args)?; + let [console, buffer_info] = this.check_shim(abi, sys_conv, link_name, args)?; this.read_target_isize(console)?; // FIXME: this should use deref_pointer_as, but CONSOLE_SCREEN_BUFFER_INFO is not in std this.deref_pointer(buffer_info)?; @@ -645,8 +618,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { this.write_null(dest)?; } "GetStdHandle" => { - let [which] = - this.check_shim(abi, ExternAbi::System { unwind: false }, link_name, args)?; + let [which] = this.check_shim(abi, sys_conv, link_name, args)?; let which = this.read_scalar(which)?.to_i32()?; // 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 @@ -655,16 +627,14 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { this.write_scalar(Scalar::from_target_isize(which.into(), this), dest)?; } "CloseHandle" => { - let [handle] = - this.check_shim(abi, ExternAbi::System { unwind: false }, link_name, args)?; + let [handle] = this.check_shim(abi, sys_conv, link_name, args)?; let ret = this.CloseHandle(handle)?; this.write_scalar(ret, dest)?; } "GetModuleFileNameW" => { - let [handle, filename, size] = - this.check_shim(abi, ExternAbi::System { unwind: false }, link_name, args)?; + let [handle, filename, size] = this.check_shim(abi, sys_conv, link_name, args)?; this.check_no_isolation("`GetModuleFileNameW`")?; let handle = this.read_target_usize(handle)?; @@ -698,7 +668,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { } "FormatMessageW" => { 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 _module = this.read_pointer(module)?; // seems to contain a module name @@ -733,29 +703,26 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // Incomplete shims that we "stub out" just to get pre-main initialization code to work. // These shims are enabled only when the caller is in the standard library. "GetProcessHeap" if this.frame_in_std() => { - let [] = - this.check_shim(abi, ExternAbi::System { unwind: false }, link_name, args)?; + let [] = this.check_shim(abi, sys_conv, link_name, args)?; // Just fake a HANDLE // It's fine to not use the Handle type here because its a stub this.write_int(1, dest)?; } "GetModuleHandleA" if this.frame_in_std() => { #[allow(non_snake_case)] - let [_lpModuleName] = - this.check_shim(abi, ExternAbi::System { unwind: false }, link_name, args)?; + let [_lpModuleName] = this.check_shim(abi, sys_conv, link_name, args)?; // We need to return something non-null here to make `compat_fn!` work. this.write_int(1, dest)?; } "SetConsoleTextAttribute" if this.frame_in_std() => { #[allow(non_snake_case)] 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. this.write_null(dest)?; } "GetConsoleMode" if this.frame_in_std() => { - let [console, mode] = - this.check_shim(abi, ExternAbi::System { unwind: false }, link_name, args)?; + let [console, mode] = this.check_shim(abi, sys_conv, link_name, args)?; this.read_target_isize(console)?; this.deref_pointer(mode)?; // Indicate an error. @@ -763,29 +730,25 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { } "GetFileType" if this.frame_in_std() => { #[allow(non_snake_case)] - let [_hFile] = - this.check_shim(abi, ExternAbi::System { unwind: false }, link_name, args)?; + let [_hFile] = this.check_shim(abi, sys_conv, link_name, args)?; // Return unknown file type. this.write_null(dest)?; } "AddVectoredExceptionHandler" if this.frame_in_std() => { #[allow(non_snake_case)] - let [_First, _Handler] = - this.check_shim(abi, ExternAbi::System { unwind: false }, link_name, args)?; + let [_First, _Handler] = 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. this.write_int(1, dest)?; } "SetThreadStackGuarantee" if this.frame_in_std() => { #[allow(non_snake_case)] - let [_StackSizeInBytes] = - this.check_shim(abi, ExternAbi::System { unwind: false }, link_name, args)?; + let [_StackSizeInBytes] = 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. this.write_int(1, dest)?; } // this is only callable from std because we know that std ignores the return value "SwitchToThread" if this.frame_in_std() => { - let [] = - this.check_shim(abi, ExternAbi::System { unwind: false }, link_name, args)?; + let [] = this.check_shim(abi, sys_conv, link_name, args)?; this.yield_active_thread(); @@ -804,8 +767,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { ); } // 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)?; return interp_ok(EmulateItemResult::NeedsUnwind); } diff --git a/src/tools/miri/src/shims/x86/aesni.rs b/src/tools/miri/src/shims/x86/aesni.rs index 4c6c1cefeb1df..c6784db67fb8e 100644 --- a/src/tools/miri/src/shims/x86/aesni.rs +++ b/src/tools/miri/src/shims/x86/aesni.rs @@ -1,7 +1,7 @@ -use rustc_abi::ExternAbi; use rustc_middle::ty::Ty; use rustc_middle::ty::layout::LayoutOf as _; use rustc_span::Symbol; +use rustc_target::callconv::{Conv, FnAbi}; use crate::*; @@ -10,7 +10,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { fn emulate_x86_aesni_intrinsic( &mut self, link_name: Symbol, - abi: ExternAbi, + abi: &FnAbi<'tcx, Ty<'tcx>>, args: &[OpTy<'tcx>], dest: &MPlaceTy<'tcx>, ) -> InterpResult<'tcx, EmulateItemResult> { @@ -26,9 +26,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // `state` with the corresponding 128-bit key of `key`. // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_aesdec_si128 "aesdec" | "aesdec.256" | "aesdec.512" => { - let [state, key] = - this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; - + let [state, key] = this.check_shim(abi, Conv::C, link_name, args)?; aes_round(this, state, key, dest, |state, key| { let key = aes::Block::from(key.to_le_bytes()); let mut state = aes::Block::from(state.to_le_bytes()); @@ -44,8 +42,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // `state` with the corresponding 128-bit key of `key`. // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_aesdeclast_si128 "aesdeclast" | "aesdeclast.256" | "aesdeclast.512" => { - let [state, key] = - this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let [state, key] = this.check_shim(abi, Conv::C, link_name, args)?; aes_round(this, state, key, dest, |state, key| { let mut state = aes::Block::from(state.to_le_bytes()); @@ -69,9 +66,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // `state` with the corresponding 128-bit key of `key`. // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_aesenc_si128 "aesenc" | "aesenc.256" | "aesenc.512" => { - let [state, key] = - this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; - + let [state, key] = this.check_shim(abi, Conv::C, link_name, args)?; aes_round(this, state, key, dest, |state, key| { let key = aes::Block::from(key.to_le_bytes()); let mut state = aes::Block::from(state.to_le_bytes()); @@ -87,9 +82,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // `state` with the corresponding 128-bit key of `key`. // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_aesenclast_si128 "aesenclast" | "aesenclast.256" | "aesenclast.512" => { - let [state, key] = - this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; - + let [state, key] = this.check_shim(abi, Conv::C, link_name, args)?; aes_round(this, state, key, dest, |state, key| { let mut state = aes::Block::from(state.to_le_bytes()); // `aes::hazmat::cipher_round` does the following operations: @@ -109,8 +102,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // Used to implement the _mm_aesimc_si128 function. // Performs the AES InvMixColumns operation on `op` "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` let op = op.transmute(this.machine.layouts.u128, this)?; let dest = dest.transmute(this.machine.layouts.u128, this)?; diff --git a/src/tools/miri/src/shims/x86/avx.rs b/src/tools/miri/src/shims/x86/avx.rs index 3971fa3b913f4..3aeb2b429dad5 100644 --- a/src/tools/miri/src/shims/x86/avx.rs +++ b/src/tools/miri/src/shims/x86/avx.rs @@ -1,9 +1,9 @@ -use rustc_abi::ExternAbi; use rustc_apfloat::ieee::{Double, Single}; use rustc_middle::mir; use rustc_middle::ty::Ty; use rustc_middle::ty::layout::LayoutOf as _; use rustc_span::Symbol; +use rustc_target::callconv::{Conv, FnAbi}; use super::{ 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( &mut self, link_name: Symbol, - abi: ExternAbi, + abi: &FnAbi<'tcx, Ty<'tcx>>, args: &[OpTy<'tcx>], dest: &MPlaceTy<'tcx>, ) -> InterpResult<'tcx, EmulateItemResult> { @@ -33,8 +33,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // matches the IEEE min/max operations, while x86 has different // semantics. "min.ps.256" | "max.ps.256" => { - let [left, right] = - this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let [left, right] = this.check_shim(abi, Conv::C, link_name, args)?; let which = match unprefixed_name { "min.ps.256" => FloatBinOp::Min, @@ -46,8 +45,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { } // Used to implement _mm256_min_pd and _mm256_max_pd functions. "min.pd.256" | "max.pd.256" => { - let [left, right] = - this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let [left, right] = this.check_shim(abi, Conv::C, link_name, args)?; let which = match unprefixed_name { "min.pd.256" => FloatBinOp::Min, @@ -60,23 +58,21 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // Used to implement the _mm256_round_ps function. // Rounds the elements of `op` according to `rounding`. "round.ps.256" => { - let [op, rounding] = - this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let [op, rounding] = this.check_shim(abi, Conv::C, link_name, args)?; round_all::(this, op, rounding, dest)?; } // Used to implement the _mm256_round_pd function. // Rounds the elements of `op` according to `rounding`. "round.pd.256" => { - let [op, rounding] = - this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let [op, rounding] = this.check_shim(abi, Conv::C, link_name, args)?; round_all::(this, op, rounding, dest)?; } // Used to implement _mm256_{rcp,rsqrt}_ps functions. // Performs the operations on all components of `op`. "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 { "rcp.ps.256" => FloatUnaryOp::Rcp, @@ -88,8 +84,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { } // Used to implement the _mm256_dp_ps function. "dp.ps.256" => { - let [left, right, imm] = - this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let [left, right, imm] = this.check_shim(abi, Conv::C, link_name, args)?; conditional_dot_product(this, left, right, imm, dest)?; } @@ -97,8 +92,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // Horizontally add/subtract adjacent floating point values // in `left` and `right`. "hadd.ps.256" | "hadd.pd.256" | "hsub.ps.256" | "hsub.pd.256" => { - let [left, right] = - this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let [left, right] = this.check_shim(abi, Conv::C, link_name, args)?; let which = match unprefixed_name { "hadd.ps.256" | "hadd.pd.256" => mir::BinOp::Add, @@ -113,8 +107,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // and `right`. For each component, returns 0 if false or u32::MAX // if true. "cmp.ps.256" => { - let [left, right, imm] = - this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let [left, right, imm] = this.check_shim(abi, Conv::C, link_name, args)?; let which = FloatBinOp::cmp_from_imm(this, this.read_scalar(imm)?.to_i8()?, link_name)?; @@ -126,8 +119,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // and `right`. For each component, returns 0 if false or u64::MAX // if true. "cmp.pd.256" => { - let [left, right, imm] = - this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let [left, right, imm] = this.check_shim(abi, Conv::C, link_name, args)?; let which = FloatBinOp::cmp_from_imm(this, this.read_scalar(imm)?.to_i8()?, link_name)?; @@ -138,7 +130,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // and _mm256_cvttpd_epi32 functions. // Converts packed f32/f64 to packed i32. "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 { // "current SSE rounding mode", assume nearest @@ -156,8 +148,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // sequence of 4-element arrays, and we shuffle each of these arrays, where // `control` determines which element of the current `data` array is written. "vpermilvar.ps" | "vpermilvar.ps.256" => { - let [data, control] = - this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let [data, control] = this.check_shim(abi, Conv::C, link_name, args)?; let (data, data_len) = this.project_to_simd(data)?; let (control, control_len) = this.project_to_simd(control)?; @@ -190,8 +181,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // where `right` determines which element of the current `left` array is // written. "vpermilvar.pd" | "vpermilvar.pd.256" => { - let [data, control] = - this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let [data, control] = this.check_shim(abi, Conv::C, link_name, args)?; let (data, data_len) = this.project_to_simd(data)?; let (control, control_len) = this.project_to_simd(control)?; @@ -223,8 +213,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // For each 128-bit element of `dest`, copies one from `left`, `right` or // zero, according to `imm`. "vperm2f128.ps.256" | "vperm2f128.pd.256" | "vperm2f128.si.256" => { - let [left, right, imm] = - this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let [left, right, imm] = this.check_shim(abi, Conv::C, link_name, args)?; assert_eq!(dest.layout, left.layout); assert_eq!(dest.layout, right.layout); @@ -267,8 +256,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // is one, it is loaded from `ptr.wrapping_add(i)`, otherwise zero is // loaded. "maskload.ps" | "maskload.pd" | "maskload.ps.256" | "maskload.pd.256" => { - let [ptr, mask] = - this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let [ptr, mask] = this.check_shim(abi, Conv::C, link_name, args)?; mask_load(this, ptr, mask, dest)?; } @@ -278,8 +266,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // is one, it is stored into `ptr.wapping_add(i)`. // Unlike SSE2's _mm_maskmoveu_si128, these are not non-temporal stores. "maskstore.ps" | "maskstore.pd" | "maskstore.ps.256" | "maskstore.pd.256" => { - let [ptr, mask, value] = - this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let [ptr, mask, value] = this.check_shim(abi, Conv::C, link_name, args)?; mask_store(this, ptr, mask, value)?; } @@ -289,8 +276,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // the data crosses a cache line, but for Miri this is just a regular // unaligned read. "ldu.dq.256" => { - let [src_ptr] = - this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let [src_ptr] = this.check_shim(abi, Conv::C, link_name, args)?; let src_ptr = this.read_pointer(src_ptr)?; let dest = dest.force_mplace(this)?; @@ -302,8 +288,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // Tests `op & mask == 0`, `op & mask == mask` or // `op & mask != 0 && op & mask != mask` "ptestz.256" | "ptestc.256" | "ptestnzc.256" => { - let [op, mask] = - this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let [op, mask] = this.check_shim(abi, Conv::C, link_name, args)?; let (all_zero, masked_set) = test_bits_masked(this, op, mask)?; let res = match unprefixed_name { @@ -326,8 +311,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { "vtestz.pd.256" | "vtestc.pd.256" | "vtestnzc.pd.256" | "vtestz.pd" | "vtestc.pd" | "vtestnzc.pd" | "vtestz.ps.256" | "vtestc.ps.256" | "vtestnzc.ps.256" | "vtestz.ps" | "vtestc.ps" | "vtestnzc.ps" => { - let [op, mask] = - this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let [op, mask] = this.check_shim(abi, Conv::C, link_name, args)?; let (direct, negated) = test_high_bits_masked(this, op, mask)?; let res = match unprefixed_name { @@ -349,7 +333,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // compiler, making these functions no-ops. // 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), } diff --git a/src/tools/miri/src/shims/x86/avx2.rs b/src/tools/miri/src/shims/x86/avx2.rs index 6aefb87d4d0e1..c79899285cd44 100644 --- a/src/tools/miri/src/shims/x86/avx2.rs +++ b/src/tools/miri/src/shims/x86/avx2.rs @@ -1,8 +1,8 @@ -use rustc_abi::ExternAbi; use rustc_middle::mir; use rustc_middle::ty::Ty; use rustc_middle::ty::layout::LayoutOf as _; use rustc_span::Symbol; +use rustc_target::callconv::{Conv, FnAbi}; use super::{ 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( &mut self, link_name: Symbol, - abi: ExternAbi, + abi: &FnAbi<'tcx, Ty<'tcx>>, args: &[OpTy<'tcx>], dest: &MPlaceTy<'tcx>, ) -> 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. // Calculates the absolute value of packed 8/16/32-bit integers. "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)?; } @@ -36,8 +36,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // Horizontally add / add with saturation / subtract adjacent 16/32-bit // integer values in `left` and `right`. "phadd.w" | "phadd.sw" | "phadd.d" | "phsub.w" | "phsub.sw" | "phsub.d" => { - let [left, right] = - this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let [left, right] = this.check_shim(abi, Conv::C, link_name, args)?; let (which, saturating) = match unprefixed_name { "phadd.w" | "phadd.d" => (mir::BinOp::Add, false), @@ -58,7 +57,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.ps.256" | "gather.q.ps" | "gather.q.ps.256" => { 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); @@ -115,8 +114,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // intermediate signed 32-bit integers. Horizontally add adjacent pairs of // intermediate 32-bit integers, and pack the results in `dest`. "pmadd.wd" => { - let [left, right] = - this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let [left, right] = this.check_shim(abi, Conv::C, link_name, args)?; let (left, left_len) = this.project_to_simd(left)?; let (right, right_len) = this.project_to_simd(right)?; @@ -152,8 +150,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // the saturating sum of the products with indices `2*i` and `2*i+1` // produces the output at index `i`. "pmadd.ub.sw" => { - let [left, right] = - this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let [left, right] = this.check_shim(abi, Conv::C, link_name, args)?; let (left, left_len) = this.project_to_simd(left)?; let (right, right_len) = this.project_to_simd(right)?; @@ -187,8 +184,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // is one, it is loaded from `ptr.wrapping_add(i)`, otherwise zero is // loaded. "maskload.d" | "maskload.q" | "maskload.d.256" | "maskload.q.256" => { - let [ptr, mask] = - this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let [ptr, mask] = this.check_shim(abi, Conv::C, link_name, args)?; mask_load(this, ptr, mask, dest)?; } @@ -198,8 +194,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // is one, it is stored into `ptr.wapping_add(i)`. // Unlike SSE2's _mm_maskmoveu_si128, these are not non-temporal stores. "maskstore.d" | "maskstore.q" | "maskstore.d.256" | "maskstore.q.256" => { - let [ptr, mask, value] = - this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let [ptr, mask, value] = this.check_shim(abi, Conv::C, link_name, args)?; mask_store(this, ptr, mask, value)?; } @@ -210,8 +205,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // offsets specified in `imm`. // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm256_mpsadbw_epu8 "mpsadbw" => { - let [left, right, imm] = - this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let [left, right, imm] = this.check_shim(abi, Conv::C, link_name, args)?; mpsadbw(this, left, right, imm, dest)?; } @@ -222,8 +216,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // 1 and then taking the bits `1..=16`. // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm256_mulhrs_epi16 "pmul.hr.sw" => { - let [left, right] = - this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let [left, right] = this.check_shim(abi, Conv::C, link_name, args)?; pmulhrsw(this, left, right, dest)?; } @@ -231,8 +224,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // Converts two 16-bit integer vectors to a single 8-bit integer // vector with signed saturation. "packsswb" => { - let [left, right] = - this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let [left, right] = this.check_shim(abi, Conv::C, link_name, args)?; packsswb(this, left, right, dest)?; } @@ -240,8 +232,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // Converts two 32-bit integer vectors to a single 16-bit integer // vector with signed saturation. "packssdw" => { - let [left, right] = - this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let [left, right] = this.check_shim(abi, Conv::C, link_name, args)?; packssdw(this, left, right, dest)?; } @@ -249,8 +240,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // Converts two 16-bit signed integer vectors to a single 8-bit // unsigned integer vector with saturation. "packuswb" => { - let [left, right] = - this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let [left, right] = this.check_shim(abi, Conv::C, link_name, args)?; packuswb(this, left, right, dest)?; } @@ -258,8 +248,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // Concatenates two 32-bit signed integer vectors and converts // the result to a 16-bit unsigned integer vector with saturation. "packusdw" => { - let [left, right] = - this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let [left, right] = this.check_shim(abi, Conv::C, link_name, args)?; packusdw(this, left, right, dest)?; } @@ -268,8 +257,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // Shuffles `left` using the three low bits of each element of `right` // as indices. "permd" | "permps" => { - let [left, right] = - this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let [left, right] = this.check_shim(abi, Conv::C, link_name, args)?; let (left, left_len) = this.project_to_simd(left)?; let (right, right_len) = this.project_to_simd(right)?; @@ -289,8 +277,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // Used to implement the _mm256_permute2x128_si256 function. // Shuffles 128-bit blocks of `a` and `b` using `imm` as pattern. "vperm2i128" => { - let [left, right, imm] = - this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let [left, right, imm] = this.check_shim(abi, Conv::C, link_name, args)?; assert_eq!(left.layout.size.bits(), 256); assert_eq!(right.layout.size.bits(), 256); @@ -327,8 +314,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // in `dest`. // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm256_sad_epu8 "psad.bw" => { - let [left, right] = - this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let [left, right] = this.check_shim(abi, Conv::C, link_name, args)?; let (left, left_len) = this.project_to_simd(left)?; let (right, right_len) = this.project_to_simd(right)?; @@ -360,8 +346,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // Shuffles bytes from `left` using `right` as pattern. // Each 128-bit block is shuffled independently. "pshuf.b" => { - let [left, right] = - this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let [left, right] = this.check_shim(abi, Conv::C, link_name, args)?; let (left, left_len) = this.project_to_simd(left)?; let (right, right_len) = this.project_to_simd(right)?; @@ -392,8 +377,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // is writen to the corresponding output element. // Basically, we multiply `left` with `right.signum()`. "psign.b" | "psign.w" | "psign.d" => { - let [left, right] = - this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let [left, right] = this.check_shim(abi, Conv::C, link_name, args)?; psign(this, left, right, dest)?; } @@ -407,8 +391,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // is copied to remaining bits. "psll.w" | "psrl.w" | "psra.w" | "psll.d" | "psrl.d" | "psra.d" | "psll.q" | "psrl.q" => { - let [left, right] = - this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let [left, right] = this.check_shim(abi, Conv::C, link_name, args)?; let which = match unprefixed_name { "psll.w" | "psll.d" | "psll.q" => ShiftOp::Left, @@ -423,8 +406,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // (except _mm{,256}_srav_epi64, which are not available in AVX2). "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" => { - let [left, right] = - this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let [left, right] = this.check_shim(abi, Conv::C, link_name, args)?; let which = match unprefixed_name { "psllv.d" | "psllv.d.256" | "psllv.q" | "psllv.q.256" => ShiftOp::Left, diff --git a/src/tools/miri/src/shims/x86/bmi.rs b/src/tools/miri/src/shims/x86/bmi.rs index 0f9e8d6f0258c..8af59df0a68ba 100644 --- a/src/tools/miri/src/shims/x86/bmi.rs +++ b/src/tools/miri/src/shims/x86/bmi.rs @@ -1,5 +1,6 @@ -use rustc_abi::ExternAbi; +use rustc_middle::ty::Ty; use rustc_span::Symbol; +use rustc_target::callconv::{Conv, FnAbi}; use crate::*; @@ -8,7 +9,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { fn emulate_x86_bmi_intrinsic( &mut self, link_name: Symbol, - abi: ExternAbi, + abi: &FnAbi<'tcx, Ty<'tcx>>, args: &[OpTy<'tcx>], dest: &MPlaceTy<'tcx>, ) -> InterpResult<'tcx, EmulateItemResult> { @@ -33,8 +34,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { return interp_ok(EmulateItemResult::NotSupported); } - let [left, right] = - this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let [left, right] = this.check_shim(abi, Conv::C, link_name, args)?; let left = this.read_scalar(left)?; let right = this.read_scalar(right)?; diff --git a/src/tools/miri/src/shims/x86/gfni.rs b/src/tools/miri/src/shims/x86/gfni.rs index 92010345f55dd..4774ec9f9d8f5 100644 --- a/src/tools/miri/src/shims/x86/gfni.rs +++ b/src/tools/miri/src/shims/x86/gfni.rs @@ -1,5 +1,6 @@ -use rustc_abi::ExternAbi; +use rustc_middle::ty::Ty; use rustc_span::Symbol; +use rustc_target::callconv::{Conv, FnAbi}; use crate::*; @@ -8,7 +9,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { fn emulate_x86_gfni_intrinsic( &mut self, link_name: Symbol, - abi: ExternAbi, + abi: &FnAbi<'tcx, Ty<'tcx>>, args: &[OpTy<'tcx>], dest: &MPlaceTy<'tcx>, ) -> InterpResult<'tcx, EmulateItemResult> { @@ -29,16 +30,14 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // See `affine_transform` for details. // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=gf2p8affine_ "vgf2p8affineqb.128" | "vgf2p8affineqb.256" | "vgf2p8affineqb.512" => { - let [left, right, imm8] = - this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let [left, right, imm8] = this.check_shim(abi, Conv::C, link_name, args)?; affine_transform(this, left, right, imm8, dest, /* inverse */ false)?; } // Used to implement the `_mm{, 256, 512}_gf2p8affineinv_epi64_epi8` functions. // See `affine_transform` for details. // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=gf2p8affineinv "vgf2p8affineinvqb.128" | "vgf2p8affineinvqb.256" | "vgf2p8affineinvqb.512" => { - let [left, right, imm8] = - this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let [left, right, imm8] = this.check_shim(abi, Conv::C, link_name, args)?; affine_transform(this, left, right, imm8, dest, /* inverse */ true)?; } // Used to implement the `_mm{, 256, 512}_gf2p8mul_epi8` functions. @@ -47,9 +46,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // polynomial representation with the reduction polynomial x^8 + x^4 + x^3 + x + 1. // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=gf2p8mul "vgf2p8mulb.128" | "vgf2p8mulb.256" | "vgf2p8mulb.512" => { - let [left, right] = - this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; - + let [left, right] = this.check_shim(abi, Conv::C, link_name, args)?; let (left, left_len) = this.project_to_simd(left)?; let (right, right_len) = this.project_to_simd(right)?; let (dest, dest_len) = this.project_to_simd(dest)?; diff --git a/src/tools/miri/src/shims/x86/mod.rs b/src/tools/miri/src/shims/x86/mod.rs index 3e02a4b363769..e57217dc6f299 100644 --- a/src/tools/miri/src/shims/x86/mod.rs +++ b/src/tools/miri/src/shims/x86/mod.rs @@ -1,10 +1,11 @@ -use rustc_abi::{ExternAbi, Size}; +use rustc_abi::Size; use rustc_apfloat::Float; use rustc_apfloat::ieee::Single; use rustc_middle::ty::Ty; use rustc_middle::ty::layout::LayoutOf as _; use rustc_middle::{mir, ty}; use rustc_span::Symbol; +use rustc_target::callconv::{Conv, FnAbi}; use self::helpers::bool_to_simd_element; use crate::*; @@ -27,7 +28,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { fn emulate_x86_intrinsic( &mut self, link_name: Symbol, - abi: ExternAbi, + abi: &FnAbi<'tcx, Ty<'tcx>>, args: &[OpTy<'tcx>], dest: &MPlaceTy<'tcx>, ) -> InterpResult<'tcx, EmulateItemResult> { @@ -45,8 +46,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { 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") { mir::BinOp::AddWithOverflow } else { @@ -68,9 +68,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { if is_u64 && this.tcx.sess.target.arch != "x86_64" { return interp_ok(EmulateItemResult::NotSupported); } - - let [c_in, a, b, out] = - this.check_shim(abi, ExternAbi::Unadjusted, link_name, args)?; + let [c_in, a, b, out] = this.check_shim(abi, Conv::C, link_name, args)?; let out = this.deref_pointer_as( out, if is_u64 { this.machine.layouts.u64 } else { this.machine.layouts.u32 }, @@ -87,7 +85,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // the instruction behaves like a no-op, so it is always safe to call the // intrinsic. "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. if this.tcx.sess.unstable_target_features.contains(&Symbol::intern("sse2")) { this.yield_active_thread(); @@ -106,8 +104,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { len = 8; } - let [left, right, imm] = - this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let [left, right, imm] = this.check_shim(abi, Conv::C, link_name, args)?; pclmulqdq(this, left, right, imm, dest, len)?; } diff --git a/src/tools/miri/src/shims/x86/sha.rs b/src/tools/miri/src/shims/x86/sha.rs index f18ff1ec253b8..6d2c151243ca1 100644 --- a/src/tools/miri/src/shims/x86/sha.rs +++ b/src/tools/miri/src/shims/x86/sha.rs @@ -4,8 +4,9 @@ //! //! [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_target::callconv::{Conv, FnAbi}; use crate::*; @@ -14,7 +15,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { fn emulate_x86_sha_intrinsic( &mut self, link_name: Symbol, - abi: ExternAbi, + abi: &FnAbi<'tcx, Ty<'tcx>>, args: &[OpTy<'tcx>], dest: &MPlaceTy<'tcx>, ) -> InterpResult<'tcx, EmulateItemResult> { @@ -51,8 +52,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { match unprefixed_name { // Used to implement the _mm_sha256rnds2_epu32 function. "256rnds2" => { - let [a, b, k] = - this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let [a, b, k] = this.check_shim(abi, Conv::C, link_name, args)?; let (a_reg, a_len) = this.project_to_simd(a)?; let (b_reg, b_len) = this.project_to_simd(b)?; @@ -73,8 +73,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { } // Used to implement the _mm_sha256msg1_epu32 function. "256msg1" => { - let [a, b] = - this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let [a, b] = this.check_shim(abi, Conv::C, link_name, args)?; let (a_reg, a_len) = this.project_to_simd(a)?; let (b_reg, b_len) = this.project_to_simd(b)?; @@ -92,8 +91,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { } // Used to implement the _mm_sha256msg2_epu32 function. "256msg2" => { - let [a, b] = - this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let [a, b] = this.check_shim(abi, Conv::C, link_name, args)?; let (a_reg, a_len) = this.project_to_simd(a)?; let (b_reg, b_len) = this.project_to_simd(b)?; diff --git a/src/tools/miri/src/shims/x86/sse.rs b/src/tools/miri/src/shims/x86/sse.rs index 9432b40a80585..fd7aba2437a5a 100644 --- a/src/tools/miri/src/shims/x86/sse.rs +++ b/src/tools/miri/src/shims/x86/sse.rs @@ -1,6 +1,7 @@ -use rustc_abi::ExternAbi; use rustc_apfloat::ieee::Single; +use rustc_middle::ty::Ty; use rustc_span::Symbol; +use rustc_target::callconv::{Conv, FnAbi}; use super::{ 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( &mut self, link_name: Symbol, - abi: ExternAbi, + abi: &FnAbi<'tcx, Ty<'tcx>>, args: &[OpTy<'tcx>], dest: &MPlaceTy<'tcx>, ) -> InterpResult<'tcx, EmulateItemResult> { @@ -32,8 +33,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // Performs the operations on the first component of `left` and // `right` and copies the remaining components from `left`. "min.ss" | "max.ss" => { - let [left, right] = - this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let [left, right] = this.check_shim(abi, Conv::C, link_name, args)?; let which = match unprefixed_name { "min.ss" => FloatBinOp::Min, @@ -49,8 +49,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // matches the IEEE min/max operations, while x86 has different // semantics. "min.ps" | "max.ps" => { - let [left, right] = - this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let [left, right] = this.check_shim(abi, Conv::C, link_name, args)?; let which = match unprefixed_name { "min.ps" => FloatBinOp::Min, @@ -64,7 +63,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // Performs the operations on the first component of `op` and // copies the remaining components from `op`. "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 { "rcp.ss" => FloatUnaryOp::Rcp, @@ -77,7 +76,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // Used to implement _mm_{sqrt,rcp,rsqrt}_ps functions. // Performs the operations on all components of `op`. "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 { "rcp.ps" => FloatUnaryOp::Rcp, @@ -96,8 +95,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // _mm_cmp{eq,lt,le,gt,ge,neq,nlt,nle,ngt,nge,ord,unord}_ss are SSE functions // with hard-coded operations. "cmp.ss" => { - let [left, right, imm] = - this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let [left, right, imm] = this.check_shim(abi, Conv::C, link_name, args)?; let which = FloatBinOp::cmp_from_imm(this, this.read_scalar(imm)?.to_i8()?, link_name)?; @@ -113,8 +111,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // _mm_cmp{eq,lt,le,gt,ge,neq,nlt,nle,ngt,nge,ord,unord}_ps are SSE functions // with hard-coded operations. "cmp.ps" => { - let [left, right, imm] = - this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let [left, right, imm] = this.check_shim(abi, Conv::C, link_name, args)?; let which = FloatBinOp::cmp_from_imm(this, this.read_scalar(imm)?.to_i8()?, link_name)?; @@ -127,8 +124,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { "comieq.ss" | "comilt.ss" | "comile.ss" | "comigt.ss" | "comige.ss" | "comineq.ss" | "ucomieq.ss" | "ucomilt.ss" | "ucomile.ss" | "ucomigt.ss" | "ucomige.ss" | "ucomineq.ss" => { - let [left, right] = - this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let [left, right] = this.check_shim(abi, Conv::C, link_name, args)?; let (left, left_len) = this.project_to_simd(left)?; let (right, right_len) = this.project_to_simd(right)?; @@ -156,7 +152,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // _mm_cvtss_si64 and _mm_cvttss_si64 functions. // Converts the first component of `op` from f32 to i32/i64. "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.read_immediate(&this.project_index(&op, 0)?)?; @@ -184,8 +180,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // are copied from `left`. // https://www.felixcloutier.com/x86/cvtsi2ss "cvtsi2ss" | "cvtsi642ss" => { - let [left, right] = - this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let [left, right] = this.check_shim(abi, Conv::C, link_name, args)?; let (left, left_len) = this.project_to_simd(left)?; let (dest, dest_len) = this.project_to_simd(dest)?; diff --git a/src/tools/miri/src/shims/x86/sse2.rs b/src/tools/miri/src/shims/x86/sse2.rs index 4ff999be7cc91..e0695b7cb7b7a 100644 --- a/src/tools/miri/src/shims/x86/sse2.rs +++ b/src/tools/miri/src/shims/x86/sse2.rs @@ -1,6 +1,7 @@ -use rustc_abi::ExternAbi; use rustc_apfloat::ieee::Double; +use rustc_middle::ty::Ty; use rustc_span::Symbol; +use rustc_target::callconv::{Conv, FnAbi}; use super::{ 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( &mut self, link_name: Symbol, - abi: ExternAbi, + abi: &FnAbi<'tcx, Ty<'tcx>>, args: &[OpTy<'tcx>], dest: &MPlaceTy<'tcx>, ) -> InterpResult<'tcx, EmulateItemResult> { @@ -39,8 +40,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // intermediate signed 32-bit integers. Horizontally add adjacent pairs of // intermediate 32-bit integers, and pack the results in `dest`. "pmadd.wd" => { - let [left, right] = - this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let [left, right] = this.check_shim(abi, Conv::C, link_name, args)?; let (left, left_len) = this.project_to_simd(left)?; let (right, right_len) = this.project_to_simd(right)?; @@ -78,8 +78,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 "psad.bw" => { - let [left, right] = - this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let [left, right] = this.check_shim(abi, Conv::C, link_name, args)?; let (left, left_len) = this.project_to_simd(left)?; let (right, right_len) = this.project_to_simd(right)?; @@ -117,8 +116,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // is copied to remaining bits. "psll.w" | "psrl.w" | "psra.w" | "psll.d" | "psrl.d" | "psra.d" | "psll.q" | "psrl.q" => { - let [left, right] = - this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let [left, right] = this.check_shim(abi, Conv::C, link_name, args)?; let which = match unprefixed_name { "psll.w" | "psll.d" | "psll.q" => ShiftOp::Left, @@ -133,7 +131,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // and _mm_cvttpd_epi32 functions. // Converts packed f32/f64 to packed i32. "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 (dest_len, _) = dest.layout.ty.simd_size_and_type(*this.tcx); @@ -170,8 +168,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // Converts two 16-bit integer vectors to a single 8-bit integer // vector with signed saturation. "packsswb.128" => { - let [left, right] = - this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let [left, right] = this.check_shim(abi, Conv::C, link_name, args)?; packsswb(this, left, right, dest)?; } @@ -179,8 +176,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // Converts two 16-bit signed integer vectors to a single 8-bit // unsigned integer vector with saturation. "packuswb.128" => { - let [left, right] = - this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let [left, right] = this.check_shim(abi, Conv::C, link_name, args)?; packuswb(this, left, right, dest)?; } @@ -188,8 +184,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // Converts two 32-bit integer vectors to a single 16-bit integer // vector with signed saturation. "packssdw.128" => { - let [left, right] = - this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let [left, right] = this.check_shim(abi, Conv::C, link_name, args)?; packssdw(this, left, right, dest)?; } @@ -199,8 +194,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // matches the IEEE min/max operations, while x86 has different // semantics. "min.sd" | "max.sd" => { - let [left, right] = - this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let [left, right] = this.check_shim(abi, Conv::C, link_name, args)?; let which = match unprefixed_name { "min.sd" => FloatBinOp::Min, @@ -216,8 +210,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // matches the IEEE min/max operations, while x86 has different // semantics. "min.pd" | "max.pd" => { - let [left, right] = - this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let [left, right] = this.check_shim(abi, Conv::C, link_name, args)?; let which = match unprefixed_name { "min.pd" => FloatBinOp::Min, @@ -236,8 +229,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // _mm_cmp{eq,lt,le,gt,ge,neq,nlt,nle,ngt,nge,ord,unord}_sd are SSE2 functions // with hard-coded operations. "cmp.sd" => { - let [left, right, imm] = - this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let [left, right, imm] = this.check_shim(abi, Conv::C, link_name, args)?; let which = FloatBinOp::cmp_from_imm(this, this.read_scalar(imm)?.to_i8()?, link_name)?; @@ -253,8 +245,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // _mm_cmp{eq,lt,le,gt,ge,neq,nlt,nle,ngt,nge,ord,unord}_pd are SSE2 functions // with hard-coded operations. "cmp.pd" => { - let [left, right, imm] = - this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let [left, right, imm] = this.check_shim(abi, Conv::C, link_name, args)?; let which = FloatBinOp::cmp_from_imm(this, this.read_scalar(imm)?.to_i8()?, link_name)?; @@ -267,8 +258,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { "comieq.sd" | "comilt.sd" | "comile.sd" | "comigt.sd" | "comige.sd" | "comineq.sd" | "ucomieq.sd" | "ucomilt.sd" | "ucomile.sd" | "ucomigt.sd" | "ucomige.sd" | "ucomineq.sd" => { - let [left, right] = - this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let [left, right] = this.check_shim(abi, Conv::C, link_name, args)?; let (left, left_len) = this.project_to_simd(left)?; let (right, right_len) = this.project_to_simd(right)?; @@ -296,7 +286,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // _mm_cvtsd_si64 and _mm_cvttsd_si64 functions. // Converts the first component of `op` from f64 to i32/i64. "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.read_immediate(&this.project_index(&op, 0)?)?; @@ -322,8 +312,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // Converts the first f64/f32 from `right` to f32/f64 and copies // the remaining elements from `left` "cvtsd2ss" | "cvtss2sd" => { - let [left, right] = - this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let [left, right] = this.check_shim(abi, Conv::C, link_name, args)?; let (left, left_len) = this.project_to_simd(left)?; let (right, _) = this.project_to_simd(right)?; diff --git a/src/tools/miri/src/shims/x86/sse3.rs b/src/tools/miri/src/shims/x86/sse3.rs index 86153d71b284c..60b7764a01e9d 100644 --- a/src/tools/miri/src/shims/x86/sse3.rs +++ b/src/tools/miri/src/shims/x86/sse3.rs @@ -1,6 +1,7 @@ -use rustc_abi::ExternAbi; use rustc_middle::mir; +use rustc_middle::ty::Ty; use rustc_span::Symbol; +use rustc_target::callconv::{Conv, FnAbi}; use super::horizontal_bin_op; use crate::*; @@ -10,7 +11,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { fn emulate_x86_sse3_intrinsic( &mut self, link_name: Symbol, - abi: ExternAbi, + abi: &FnAbi<'tcx, Ty<'tcx>>, args: &[OpTy<'tcx>], dest: &MPlaceTy<'tcx>, ) -> InterpResult<'tcx, EmulateItemResult> { @@ -24,8 +25,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // Horizontally add/subtract adjacent floating point values // in `left` and `right`. "hadd.ps" | "hadd.pd" | "hsub.ps" | "hsub.pd" => { - let [left, right] = - this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let [left, right] = this.check_shim(abi, Conv::C, link_name, args)?; let which = match unprefixed_name { "hadd.ps" | "hadd.pd" => mir::BinOp::Add, @@ -41,8 +41,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // the data crosses a cache line, but for Miri this is just a regular // unaligned read. "ldu.dq" => { - let [src_ptr] = - this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let [src_ptr] = this.check_shim(abi, Conv::C, link_name, args)?; let src_ptr = this.read_pointer(src_ptr)?; let dest = dest.force_mplace(this)?; diff --git a/src/tools/miri/src/shims/x86/sse41.rs b/src/tools/miri/src/shims/x86/sse41.rs index b81d6f24141bf..93d689a3044e3 100644 --- a/src/tools/miri/src/shims/x86/sse41.rs +++ b/src/tools/miri/src/shims/x86/sse41.rs @@ -1,5 +1,6 @@ -use rustc_abi::ExternAbi; +use rustc_middle::ty::Ty; 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 crate::*; @@ -9,7 +10,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { fn emulate_x86_sse41_intrinsic( &mut self, link_name: Symbol, - abi: ExternAbi, + abi: &FnAbi<'tcx, Ty<'tcx>>, args: &[OpTy<'tcx>], dest: &MPlaceTy<'tcx>, ) -> InterpResult<'tcx, EmulateItemResult> { @@ -26,8 +27,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // bits `4..=5` if `imm`, and `i`th bit specifies whether element // `i` is zeroed. "insertps" => { - let [left, right, imm] = - this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let [left, right, imm] = this.check_shim(abi, Conv::C, link_name, args)?; let (left, left_len) = this.project_to_simd(left)?; let (right, right_len) = this.project_to_simd(right)?; @@ -62,8 +62,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // Concatenates two 32-bit signed integer vectors and converts // the result to a 16-bit unsigned integer vector with saturation. "packusdw" => { - let [left, right] = - this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let [left, right] = this.check_shim(abi, Conv::C, link_name, args)?; packusdw(this, left, right, dest)?; } @@ -73,8 +72,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // products, and conditionally stores the sum in `dest` using the low // 4 bits of `imm`. "dpps" | "dppd" => { - let [left, right, imm] = - this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let [left, right, imm] = this.check_shim(abi, Conv::C, link_name, args)?; conditional_dot_product(this, left, right, imm, dest)?; } @@ -82,16 +80,14 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // functions. Rounds the first element of `right` according to `rounding` // and copies the remaining elements from `left`. "round.ss" => { - let [left, right, rounding] = - this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let [left, right, rounding] = this.check_shim(abi, Conv::C, link_name, args)?; round_first::(this, left, right, rounding, dest)?; } // Used to implement the _mm_floor_ps, _mm_ceil_ps and _mm_round_ps // functions. Rounds the elements of `op` according to `rounding`. "round.ps" => { - let [op, rounding] = - this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let [op, rounding] = this.check_shim(abi, Conv::C, link_name, args)?; round_all::(this, op, rounding, dest)?; } @@ -99,16 +95,14 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // functions. Rounds the first element of `right` according to `rounding` // and copies the remaining elements from `left`. "round.sd" => { - let [left, right, rounding] = - this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let [left, right, rounding] = this.check_shim(abi, Conv::C, link_name, args)?; round_first::(this, left, right, rounding, dest)?; } // Used to implement the _mm_floor_pd, _mm_ceil_pd and _mm_round_pd // functions. Rounds the elements of `op` according to `rounding`. "round.pd" => { - let [op, rounding] = - this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let [op, rounding] = this.check_shim(abi, Conv::C, link_name, args)?; round_all::(this, op, rounding, dest)?; } @@ -116,7 +110,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // Find the minimum unsinged 16-bit integer in `op` and // returns its value and position. "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 (dest, dest_len) = this.project_to_simd(dest)?; @@ -150,8 +144,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // offsets specified in `imm`. // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_mpsadbw_epu8 "mpsadbw" => { - let [left, right, imm] = - this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let [left, right, imm] = this.check_shim(abi, Conv::C, link_name, args)?; mpsadbw(this, left, right, imm, dest)?; } @@ -160,8 +153,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // Tests `(op & mask) == 0`, `(op & mask) == mask` or // `(op & mask) != 0 && (op & mask) != mask` "ptestz" | "ptestc" | "ptestnzc" => { - let [op, mask] = - this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let [op, mask] = this.check_shim(abi, Conv::C, link_name, args)?; let (all_zero, masked_set) = test_bits_masked(this, op, mask)?; let res = match unprefixed_name { diff --git a/src/tools/miri/src/shims/x86/sse42.rs b/src/tools/miri/src/shims/x86/sse42.rs index 0b058a9911e2a..02336a722f7ed 100644 --- a/src/tools/miri/src/shims/x86/sse42.rs +++ b/src/tools/miri/src/shims/x86/sse42.rs @@ -1,8 +1,9 @@ -use rustc_abi::{ExternAbi, Size}; +use rustc_abi::Size; use rustc_middle::mir; use rustc_middle::ty::Ty; use rustc_middle::ty::layout::LayoutOf as _; use rustc_span::Symbol; +use rustc_target::callconv::{Conv, FnAbi}; use crate::*; @@ -200,7 +201,7 @@ fn deconstruct_args<'tcx>( unprefixed_name: &str, ecx: &mut MiriInterpCx<'tcx>, link_name: Symbol, - abi: ExternAbi, + abi: &FnAbi<'tcx, Ty<'tcx>>, args: &[OpTy<'tcx>], ) -> InterpResult<'tcx, (OpTy<'tcx>, OpTy<'tcx>, Option<(u64, u64)>, u8)> { let array_layout_fn = |ecx: &mut MiriInterpCx<'tcx>, imm: u8| { @@ -222,8 +223,7 @@ fn deconstruct_args<'tcx>( }; if is_explicit { - let [str1, len1, str2, len2, imm] = - ecx.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let [str1, len1, str2, len2, imm] = ecx.check_shim(abi, Conv::C, link_name, args)?; let imm = ecx.read_scalar(imm)?.to_u8()?; let default_len = default_len::(imm); @@ -236,8 +236,7 @@ fn deconstruct_args<'tcx>( interp_ok((str1, str2, Some((len1, len2)), imm)) } else { - let [str1, str2, imm] = - ecx.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let [str1, str2, imm] = ecx.check_shim(abi, Conv::C, link_name, args)?; let imm = ecx.read_scalar(imm)?.to_u8()?; let array_layout = array_layout_fn(ecx, imm)?; @@ -279,7 +278,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { fn emulate_x86_sse42_intrinsic( &mut self, link_name: Symbol, - abi: ExternAbi, + abi: &FnAbi<'tcx, Ty<'tcx>>, args: &[OpTy<'tcx>], dest: &MPlaceTy<'tcx>, ) -> InterpResult<'tcx, EmulateItemResult> { @@ -387,8 +386,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // search for a null terminator (see `deconstruct_args` for more details). // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#ig_expand=924,925 "pcmpistriz128" | "pcmpistris128" => { - let [str1, str2, imm] = - this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let [str1, str2, imm] = this.check_shim(abi, Conv::C, link_name, args)?; let imm = this.read_scalar(imm)?.to_u8()?; let str = if unprefixed_name == "pcmpistris128" { str1 } else { str2 }; @@ -408,8 +406,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // than 16 for byte-sized operands or 8 for word-sized operands. // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#ig_expand=1046,1047 "pcmpestriz128" | "pcmpestris128" => { - let [_, len1, _, len2, imm] = - this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let [_, len1, _, len2, imm] = this.check_shim(abi, Conv::C, link_name, args)?; let len = if unprefixed_name == "pcmpestris128" { len1 } else { len2 }; let len = this.read_scalar(len)?.to_i32()?; let imm = this.read_scalar(imm)?.to_u8()?; @@ -436,8 +433,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { return interp_ok(EmulateItemResult::NotSupported); } - let [left, right] = - this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let [left, right] = this.check_shim(abi, Conv::C, link_name, args)?; let left = this.read_scalar(left)?; let right = this.read_scalar(right)?; diff --git a/src/tools/miri/src/shims/x86/ssse3.rs b/src/tools/miri/src/shims/x86/ssse3.rs index cdab78bc7427a..f3e9ac0e5dc99 100644 --- a/src/tools/miri/src/shims/x86/ssse3.rs +++ b/src/tools/miri/src/shims/x86/ssse3.rs @@ -1,6 +1,7 @@ -use rustc_abi::ExternAbi; use rustc_middle::mir; +use rustc_middle::ty::Ty; use rustc_span::Symbol; +use rustc_target::callconv::{Conv, FnAbi}; use super::{horizontal_bin_op, int_abs, pmulhrsw, psign}; use crate::*; @@ -10,7 +11,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { fn emulate_x86_ssse3_intrinsic( &mut self, link_name: Symbol, - abi: ExternAbi, + abi: &FnAbi<'tcx, Ty<'tcx>>, args: &[OpTy<'tcx>], dest: &MPlaceTy<'tcx>, ) -> 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. // Calculates the absolute value of packed 8/16/32-bit integers. "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)?; } @@ -31,8 +32,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // Shuffles bytes from `left` using `right` as pattern. // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_shuffle_epi8 "pshuf.b.128" => { - let [left, right] = - this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let [left, right] = this.check_shim(abi, Conv::C, link_name, args)?; let (left, left_len) = this.project_to_simd(left)?; let (right, right_len) = this.project_to_simd(right)?; @@ -61,8 +61,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // integer values in `left` and `right`. "phadd.w.128" | "phadd.sw.128" | "phadd.d.128" | "phsub.w.128" | "phsub.sw.128" | "phsub.d.128" => { - let [left, right] = - this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let [left, right] = this.check_shim(abi, Conv::C, link_name, args)?; let (which, saturating) = match unprefixed_name { "phadd.w.128" | "phadd.d.128" => (mir::BinOp::Add, false), @@ -81,8 +80,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // produces the output at index `i`. // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_maddubs_epi16 "pmadd.ub.sw.128" => { - let [left, right] = - this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let [left, right] = this.check_shim(abi, Conv::C, link_name, args)?; let (left, left_len) = this.project_to_simd(left)?; let (right, right_len) = this.project_to_simd(right)?; @@ -117,8 +115,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // 1 and then taking the bits `1..=16`. // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_mulhrs_epi16 "pmul.hr.sw.128" => { - let [left, right] = - this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let [left, right] = this.check_shim(abi, Conv::C, link_name, args)?; pmulhrsw(this, left, right, dest)?; } @@ -128,8 +125,7 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // is writen to the corresponding output element. // Basically, we multiply `left` with `right.signum()`. "psign.b.128" | "psign.w.128" | "psign.d.128" => { - let [left, right] = - this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let [left, right] = this.check_shim(abi, Conv::C, link_name, args)?; psign(this, left, right, dest)?; } diff --git a/tests/run-make/rustdoc-default-output/output-default.stdout b/tests/run-make/rustdoc-default-output/output-default.stdout index 125443ce61964..c2d9309ba2e6d 100644 --- a/tests/run-make/rustdoc-default-output/output-default.stdout +++ b/tests/run-make/rustdoc-default-output/output-default.stdout @@ -189,6 +189,10 @@ Options: --include-parts-dir path/to/doc.parts/ Includes trait implementations and other crate info from provided path. Only use with --merge=finalize + --html-no-source + Disable HTML source code pages generation + --doctest-compilation-args add arguments to be used when compiling doctests + --disable-minification removed --plugin-path DIR @@ -209,8 +213,6 @@ Options: removed, see issue #44136 for more information - --html-no-source - Disable HTML source code pages generation @path Read newline separated options from `path` diff --git a/tests/rustdoc-ui/doctest/rustflags-multiple-args.rs b/tests/rustdoc-ui/doctest/rustflags-multiple-args.rs new file mode 100644 index 0000000000000..8519920e53bef --- /dev/null +++ b/tests/rustdoc-ui/doctest/rustflags-multiple-args.rs @@ -0,0 +1,17 @@ +// This test checks that the test behave when `--doctest-compilation-args` is passed +// multiple times. + +//@ check-pass +//@ compile-flags: --test -Zunstable-options --doctest-compilation-args=--cfg=testcase_must_be_present +//@ compile-flags: --doctest-compilation-args=--cfg=another +//@ normalize-stdout-test: "tests/rustdoc-ui/doctest" -> "$$DIR" +//@ normalize-stdout-test: "finished in \d+\.\d+s" -> "finished in $$TIME" + +/// ``` +/// #[cfg(testcase_must_be_present)] +/// #[cfg(another)] +/// fn must_be_present() {} +/// +/// fn main() { must_be_present() } +/// ``` +pub struct Bar; diff --git a/tests/rustdoc-ui/doctest/rustflags-multiple-args.stdout b/tests/rustdoc-ui/doctest/rustflags-multiple-args.stdout new file mode 100644 index 0000000000000..0e8a9e1efcf6f --- /dev/null +++ b/tests/rustdoc-ui/doctest/rustflags-multiple-args.stdout @@ -0,0 +1,6 @@ + +running 1 test +test $DIR/rustflags-multiple-args.rs - Bar (line 10) ... ok + +test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME + diff --git a/tests/rustdoc-ui/doctest/rustflags.rs b/tests/rustdoc-ui/doctest/rustflags.rs new file mode 100644 index 0000000000000..fa460e355472a --- /dev/null +++ b/tests/rustdoc-ui/doctest/rustflags.rs @@ -0,0 +1,12 @@ +//@ check-pass +//@ compile-flags: --test -Zunstable-options --doctest-compilation-args=--cfg=testcase_must_be_present +//@ normalize-stdout-test: "tests/rustdoc-ui/doctest" -> "$$DIR" +//@ normalize-stdout-test: "finished in \d+\.\d+s" -> "finished in $$TIME" + +/// ``` +/// #[cfg(testcase_must_be_present)] +/// fn must_be_present() {} +/// +/// fn main() { must_be_present() } +/// ``` +pub struct Bar; diff --git a/tests/rustdoc-ui/doctest/rustflags.stdout b/tests/rustdoc-ui/doctest/rustflags.stdout new file mode 100644 index 0000000000000..b9da6637745bc --- /dev/null +++ b/tests/rustdoc-ui/doctest/rustflags.stdout @@ -0,0 +1,6 @@ + +running 1 test +test $DIR/rustflags.rs - Bar (line 6) ... ok + +test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME + diff --git a/tests/rustdoc/assoc-consts-underscore.rs b/tests/rustdoc/assoc-consts-underscore.rs new file mode 100644 index 0000000000000..f48098094db58 --- /dev/null +++ b/tests/rustdoc/assoc-consts-underscore.rs @@ -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: () }; +} diff --git a/tests/rustdoc/bold-tag-101743.rs b/tests/rustdoc/bold-tag-101743.rs index a81767eeeeb63..3cd4005a4fadf 100644 --- a/tests/rustdoc/bold-tag-101743.rs +++ b/tests/rustdoc/bold-tag-101743.rs @@ -14,6 +14,6 @@ impl Repr { // If we change back to rendering the value of consts, check this doesn't add // a 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::(); }