diff options
| author | bors <bors@rust-lang.org> | 2025-06-03 23:15:53 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2025-06-03 23:15:53 +0000 |
| commit | 792fc2b033aea7ea7b766e38bdc40f7d6bdce8c3 (patch) | |
| tree | efa05e53a722ff840a419b9cfad33c61d41c2361 /compiler | |
| parent | 59aa1e873028948faaf8b97e5e02d4db340ad7b1 (diff) | |
| parent | a2b6f14af375a8338329c10f93e6eb4c7890b2ef (diff) | |
Auto merge of #141984 - matthiaskrgr:rollup-wy6j9ca, r=matthiaskrgr
Rollup of 8 pull requests Successful merges: - rust-lang/rust#137725 (Add `iter` macro) - rust-lang/rust#141455 (std: abort the process on failure to allocate a TLS key) - rust-lang/rust#141569 (Replace ad-hoc ABI "adjustments" with an `AbiMap` to `CanonAbi`) - rust-lang/rust#141698 (Use the informative error as the main const eval error message) - rust-lang/rust#141925 (Remove bootstrap cfgs from library/) - rust-lang/rust#141943 (Remove pre-expansion AST stats.) - rust-lang/rust#141945 (Remove `Path::is_ident`.) - rust-lang/rust#141957 (Add missing `dyn` keywords to tests that do not test for them Part 2) r? `@ghost` `@rustbot` modify labels: rollup
Diffstat (limited to 'compiler')
40 files changed, 711 insertions, 579 deletions
diff --git a/compiler/rustc_abi/src/canon_abi.rs b/compiler/rustc_abi/src/canon_abi.rs new file mode 100644 index 00000000000..2cf7648a859 --- /dev/null +++ b/compiler/rustc_abi/src/canon_abi.rs @@ -0,0 +1,136 @@ +use std::fmt; + +#[cfg(feature = "nightly")] +use rustc_macros::HashStable_Generic; + +use crate::ExternAbi; + +/// Calling convention to determine codegen +/// +/// CanonAbi erases certain distinctions ExternAbi preserves, but remains target-dependent. +/// There are still both target-specific variants and aliasing variants, though much fewer. +/// The reason for this step is the frontend may wish to show an ExternAbi but implement that ABI +/// using a different ABI than the string per se, or describe irrelevant differences, e.g. +/// - extern "system" +/// - extern "cdecl" +/// - extern "C-unwind" +/// In that sense, this erases mere syntactic distinctions to create a canonical *directive*, +/// rather than picking the "actual" ABI. +#[derive(Copy, Clone, Debug)] +#[derive(PartialOrd, Ord, PartialEq, Eq, Hash)] +#[cfg_attr(feature = "nightly", derive(HashStable_Generic))] +pub enum CanonAbi { + // NOTE: the use of nested variants for some ABIs is for many targets they don't matter, + // and this pushes the complexity of their reasoning to target-specific code, + // allowing a `match` to easily exhaustively ignore these subcategories of variants. + // Otherwise it is very tempting to avoid matching exhaustively! + C, + Rust, + RustCold, + + /// ABIs relevant to 32-bit Arm targets + Arm(ArmCall), + /// ABI relevant to GPUs: the entry point for a GPU kernel + GpuKernel, + + /// ABIs relevant to bare-metal interrupt targets + // FIXME(workingjubilee): a particular reason for this nesting is we might not need these? + // interrupt ABIs should have the same properties: + // - uncallable by Rust calls, as LLVM rejects it in most cases + // - uses a preserve-all-registers *callee* convention + // - should always return `-> !` (effectively... it can't use normal `ret`) + // what differs between targets is + // - allowed arguments: x86 differs slightly, having 2-3 arguments which are handled magically + // - may need special prologues/epilogues for some interrupts, without affecting "call ABI" + Interrupt(InterruptKind), + + /// ABIs relevant to Windows or x86 targets + X86(X86Call), +} + +impl fmt::Display for CanonAbi { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + self.to_erased_extern_abi().as_str().fmt(f) + } +} + +impl CanonAbi { + /// convert to the ExternAbi that *shares a string* with this CanonAbi + /// + /// A target-insensitive mapping of CanonAbi to ExternAbi, convenient for "forwarding" impls. + /// Importantly, the set of CanonAbi values is a logical *subset* of ExternAbi values, + /// so this is injective: if you take an ExternAbi to a CanonAbi and back, you have lost data. + const fn to_erased_extern_abi(self) -> ExternAbi { + match self { + CanonAbi::C => ExternAbi::C { unwind: false }, + CanonAbi::Rust => ExternAbi::Rust, + CanonAbi::RustCold => ExternAbi::RustCold, + CanonAbi::Arm(arm_call) => match arm_call { + ArmCall::Aapcs => ExternAbi::Aapcs { unwind: false }, + ArmCall::CCmseNonSecureCall => ExternAbi::CCmseNonSecureCall, + ArmCall::CCmseNonSecureEntry => ExternAbi::CCmseNonSecureEntry, + }, + CanonAbi::GpuKernel => ExternAbi::GpuKernel, + CanonAbi::Interrupt(interrupt_kind) => match interrupt_kind { + InterruptKind::Avr => ExternAbi::AvrInterrupt, + InterruptKind::AvrNonBlocking => ExternAbi::AvrNonBlockingInterrupt, + InterruptKind::Msp430 => ExternAbi::Msp430Interrupt, + InterruptKind::RiscvMachine => ExternAbi::RiscvInterruptM, + InterruptKind::RiscvSupervisor => ExternAbi::RiscvInterruptS, + InterruptKind::X86 => ExternAbi::X86Interrupt, + }, + CanonAbi::X86(x86_call) => match x86_call { + X86Call::Fastcall => ExternAbi::Fastcall { unwind: false }, + X86Call::Stdcall => ExternAbi::Stdcall { unwind: false }, + X86Call::SysV64 => ExternAbi::SysV64 { unwind: false }, + X86Call::Thiscall => ExternAbi::Thiscall { unwind: false }, + X86Call::Vectorcall => ExternAbi::Vectorcall { unwind: false }, + X86Call::Win64 => ExternAbi::Win64 { unwind: false }, + }, + } + } +} + +/// Callee codegen for interrupts +/// +/// This is named differently from the "Call" enums because it is different: +/// these "ABI" differences are not relevant to callers, since there is "no caller". +/// These only affect callee codegen. making their categorization as distinct ABIs a bit peculiar. +#[derive(Copy, Clone, Debug)] +#[derive(PartialOrd, Ord, PartialEq, Eq, Hash)] +#[cfg_attr(feature = "nightly", derive(HashStable_Generic))] +pub enum InterruptKind { + Avr, + AvrNonBlocking, + Msp430, + RiscvMachine, + RiscvSupervisor, + X86, +} + +/// ABIs defined for x86-{32,64} +/// +/// One of SysV64 or Win64 may alias the C ABI, and arguably Win64 is cross-platform now? +#[derive(Clone, Copy, Debug)] +#[derive(PartialOrd, Ord, PartialEq, Eq, Hash)] +#[cfg_attr(feature = "nightly", derive(HashStable_Generic))] +pub enum X86Call { + /// "fastcall" has both GNU and Windows variants + Fastcall, + /// "stdcall" has both GNU and Windows variants + Stdcall, + SysV64, + Thiscall, + Vectorcall, + Win64, +} + +/// ABIs defined for 32-bit Arm +#[derive(Copy, Clone, Debug)] +#[derive(PartialOrd, Ord, PartialEq, Eq, Hash)] +#[cfg_attr(feature = "nightly", derive(HashStable_Generic))] +pub enum ArmCall { + Aapcs, + CCmseNonSecureCall, + CCmseNonSecureEntry, +} diff --git a/compiler/rustc_abi/src/extern_abi.rs b/compiler/rustc_abi/src/extern_abi.rs index 55f4845d216..c48920e5f1b 100644 --- a/compiler/rustc_abi/src/extern_abi.rs +++ b/compiler/rustc_abi/src/extern_abi.rs @@ -7,6 +7,8 @@ use rustc_data_structures::stable_hasher::{HashStable, StableHasher, StableOrd}; #[cfg(feature = "nightly")] use rustc_macros::{Decodable, Encodable}; +use crate::AbiFromStrErr; + #[cfg(test)] mod tests; @@ -99,11 +101,6 @@ macro_rules! abi_impls { } } -#[derive(Debug)] -pub enum AbiFromStrErr { - Unknown, -} - abi_impls! { ExternAbi = { C { unwind: false } =><= "C", diff --git a/compiler/rustc_abi/src/lib.rs b/compiler/rustc_abi/src/lib.rs index 59b74d29221..b806d0aba31 100644 --- a/compiler/rustc_abi/src/lib.rs +++ b/compiler/rustc_abi/src/lib.rs @@ -55,13 +55,14 @@ use rustc_index::{Idx, IndexSlice, IndexVec}; use rustc_macros::{Decodable_NoContext, Encodable_NoContext, HashStable_Generic}; mod callconv; +mod canon_abi; +mod extern_abi; mod layout; #[cfg(test)] mod tests; -mod extern_abi; - pub use callconv::{Heterogeneous, HomogeneousAggregate, Reg, RegKind}; +pub use canon_abi::{ArmCall, CanonAbi, InterruptKind, X86Call}; pub use extern_abi::{ExternAbi, all_names}; #[cfg(feature = "nightly")] pub use layout::{FIRST_VARIANT, FieldIdx, Layout, TyAbiInterface, TyAndLayout, VariantIdx}; @@ -1895,3 +1896,11 @@ pub enum StructKind { /// A univariant, but with a prefix of an arbitrary size & alignment (e.g., enum tag). Prefixed(Size, Align), } + +#[derive(Clone, Debug)] +pub enum AbiFromStrErr { + /// not a known ABI + Unknown, + /// no "-unwind" variant can be used here + NoExplicitUnwind, +} diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 5c122ff0bbc..c9a8adec31a 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -99,8 +99,15 @@ pub struct Path { impl PartialEq<Symbol> for Path { #[inline] - fn eq(&self, symbol: &Symbol) -> bool { - matches!(&self.segments[..], [segment] if segment.ident.name == *symbol) + fn eq(&self, name: &Symbol) -> bool { + if let [segment] = self.segments.as_ref() + && segment.args.is_none() + && segment.ident.name == *name + { + true + } else { + false + } } } @@ -120,17 +127,6 @@ impl Path { Path { segments: thin_vec![PathSegment::from_ident(ident)], span: ident.span, tokens: None } } - pub fn is_ident(&self, name: Symbol) -> bool { - if let [segment] = self.segments.as_ref() - && segment.args.is_none() - && segment.ident.name == name - { - true - } else { - false - } - } - pub fn is_global(&self) -> bool { self.segments.first().is_some_and(|segment| segment.ident.name == kw::PathRoot) } diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index 9f3aed9216c..537d4a2a6af 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -1,4 +1,3 @@ -use std::assert_matches::assert_matches; use std::ops::ControlFlow; use std::sync::Arc; @@ -1199,11 +1198,13 @@ impl<'hir> LoweringContext<'_, 'hir> { let closure_def_id = self.local_def_id(closure_id); let (binder_clause, generic_params) = self.lower_closure_binder(binder); - assert_matches!( - coroutine_kind, - CoroutineKind::Async { .. }, - "only async closures are supported currently" - ); + let coroutine_desugaring = match coroutine_kind { + CoroutineKind::Async { .. } => hir::CoroutineDesugaring::Async, + CoroutineKind::Gen { .. } => hir::CoroutineDesugaring::Gen, + CoroutineKind::AsyncGen { span, .. } => { + span_bug!(span, "only async closures and `iter!` closures are supported currently") + } + }; let body = self.with_new_scopes(fn_decl_span, |this| { let inner_decl = @@ -1247,7 +1248,7 @@ impl<'hir> LoweringContext<'_, 'hir> { // Lower this as a `CoroutineClosure`. That will ensure that HIR typeck // knows that a `FnDecl` output type like `-> &str` actually means // "coroutine that returns &str", rather than directly returning a `&str`. - kind: hir::ClosureKind::CoroutineClosure(hir::CoroutineDesugaring::Async), + kind: hir::ClosureKind::CoroutineClosure(coroutine_desugaring), constness: hir::Constness::NotConst, }); hir::ExprKind::Closure(c) diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs index 915613a3913..3682d25d341 100644 --- a/compiler/rustc_ast_passes/src/feature_gate.rs +++ b/compiler/rustc_ast_passes/src/feature_gate.rs @@ -477,11 +477,12 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) { for span in spans { if (!visitor.features.coroutines() && !span.allows_unstable(sym::coroutines)) && (!visitor.features.gen_blocks() && !span.allows_unstable(sym::gen_blocks)) + && (!visitor.features.yield_expr() && !span.allows_unstable(sym::yield_expr)) { #[allow(rustc::untranslatable_diagnostic)] - // Don't know which of the two features to include in the - // error message, so I am arbitrarily picking one. - feature_err(&visitor.sess, sym::coroutines, *span, "yield syntax is experimental") + // Emit yield_expr as the error, since that will be sufficient. You can think of it + // as coroutines and gen_blocks imply yield_expr. + feature_err(&visitor.sess, sym::yield_expr, *span, "yield syntax is experimental") .emit(); } } diff --git a/compiler/rustc_borrowck/src/type_check/input_output.rs b/compiler/rustc_borrowck/src/type_check/input_output.rs index c6b29fe36fd..0c46e0c0c22 100644 --- a/compiler/rustc_borrowck/src/type_check/input_output.rs +++ b/compiler/rustc_borrowck/src/type_check/input_output.rs @@ -52,7 +52,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { assert_matches!( self.tcx().coroutine_kind(self.tcx().coroutine_for_closure(mir_def_id)), Some(hir::CoroutineKind::Desugared( - hir::CoroutineDesugaring::Async, + hir::CoroutineDesugaring::Async | hir::CoroutineDesugaring::Gen, hir::CoroutineSource::Closure )), "this needs to be modified if we're lowering non-async closures" diff --git a/compiler/rustc_builtin_macros/src/iter.rs b/compiler/rustc_builtin_macros/src/iter.rs new file mode 100644 index 00000000000..7ad83903a1b --- /dev/null +++ b/compiler/rustc_builtin_macros/src/iter.rs @@ -0,0 +1,53 @@ +use rustc_ast::ptr::P; +use rustc_ast::tokenstream::TokenStream; +use rustc_ast::{CoroutineKind, DUMMY_NODE_ID, Expr, ast, token}; +use rustc_errors::PResult; +use rustc_expand::base::{self, DummyResult, ExpandResult, ExtCtxt, MacroExpanderResult}; +use rustc_span::Span; + +pub(crate) fn expand<'cx>( + cx: &'cx mut ExtCtxt<'_>, + sp: Span, + tts: TokenStream, +) -> MacroExpanderResult<'cx> { + let closure = match parse_closure(cx, sp, tts) { + Ok(parsed) => parsed, + Err(err) => { + return ExpandResult::Ready(DummyResult::any(sp, err.emit())); + } + }; + + ExpandResult::Ready(base::MacEager::expr(closure)) +} + +fn parse_closure<'a>( + cx: &mut ExtCtxt<'a>, + span: Span, + stream: TokenStream, +) -> PResult<'a, P<Expr>> { + let mut closure_parser = cx.new_parser_from_tts(stream); + + let coroutine_kind = Some(CoroutineKind::Gen { + span, + closure_id: DUMMY_NODE_ID, + return_impl_trait_id: DUMMY_NODE_ID, + }); + + let mut closure = closure_parser.parse_expr()?; + match &mut closure.kind { + ast::ExprKind::Closure(c) => { + if let Some(kind) = c.coroutine_kind { + cx.dcx().span_err(kind.span(), "only plain closures allowed in `iter!`"); + } + c.coroutine_kind = coroutine_kind; + if closure_parser.token != token::Eof { + closure_parser.unexpected()?; + } + Ok(closure) + } + _ => { + cx.dcx().span_err(closure.span, "`iter!` body must be a closure"); + Err(closure_parser.unexpected().unwrap_err()) + } + } +} diff --git a/compiler/rustc_builtin_macros/src/lib.rs b/compiler/rustc_builtin_macros/src/lib.rs index 667d90429f2..aa52c3bd281 100644 --- a/compiler/rustc_builtin_macros/src/lib.rs +++ b/compiler/rustc_builtin_macros/src/lib.rs @@ -47,6 +47,7 @@ mod errors; mod format; mod format_foreign; mod global_allocator; +mod iter; mod log_syntax; mod pattern_type; mod source_util; @@ -95,6 +96,7 @@ pub fn register_builtin_macros(resolver: &mut dyn ResolverExpand) { include: source_util::expand_include, include_bytes: source_util::expand_include_bytes, include_str: source_util::expand_include_str, + iter: iter::expand, line: source_util::expand_line, log_syntax: log_syntax::expand_log_syntax, module_path: source_util::expand_mod, diff --git a/compiler/rustc_codegen_cranelift/src/abi/mod.rs b/compiler/rustc_codegen_cranelift/src/abi/mod.rs index 5f7bf3821d7..fe5b220117f 100644 --- a/compiler/rustc_codegen_cranelift/src/abi/mod.rs +++ b/compiler/rustc_codegen_cranelift/src/abi/mod.rs @@ -10,7 +10,7 @@ use std::mem; use cranelift_codegen::ir::{ArgumentPurpose, SigRef}; use cranelift_codegen::isa::CallConv; use cranelift_module::ModuleError; -use rustc_abi::ExternAbi; +use rustc_abi::{CanonAbi, ExternAbi, X86Call}; use rustc_codegen_ssa::base::is_call_from_compiler_builtins_to_upstream_monomorphization; use rustc_codegen_ssa::errors::CompilerBuiltinsCannotCall; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; @@ -19,7 +19,7 @@ use rustc_middle::ty::layout::FnAbiOf; use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_session::Session; use rustc_span::source_map::Spanned; -use rustc_target::callconv::{Conv, FnAbi, PassMode}; +use rustc_target::callconv::{FnAbi, PassMode}; use smallvec::SmallVec; use self::pass_mode::*; @@ -42,32 +42,27 @@ fn clif_sig_from_fn_abi<'tcx>( Signature { params, returns, call_conv } } -pub(crate) fn conv_to_call_conv(sess: &Session, c: Conv, default_call_conv: CallConv) -> CallConv { +pub(crate) fn conv_to_call_conv( + sess: &Session, + c: CanonAbi, + default_call_conv: CallConv, +) -> CallConv { match c { - Conv::Rust | Conv::C => default_call_conv, - Conv::Cold | Conv::PreserveMost | Conv::PreserveAll => CallConv::Cold, - Conv::X86_64SysV => CallConv::SystemV, - Conv::X86_64Win64 => CallConv::WindowsFastcall, - - // Should already get a back compat warning - Conv::X86Fastcall | Conv::X86Stdcall | Conv::X86ThisCall | Conv::X86VectorCall => { - default_call_conv - } - - Conv::X86Intr | Conv::RiscvInterrupt { .. } => { - sess.dcx().fatal(format!("interrupt call conv {c:?} not yet implemented")) + CanonAbi::Rust | CanonAbi::C => default_call_conv, + CanonAbi::RustCold => CallConv::Cold, + + CanonAbi::X86(x86_call) => match x86_call { + X86Call::SysV64 => CallConv::SystemV, + X86Call::Win64 => CallConv::WindowsFastcall, + // Should already get a back compat warning + _ => default_call_conv, + }, + + CanonAbi::Interrupt(_) | CanonAbi::Arm(_) => { + sess.dcx().fatal("call conv {c:?} is not yet implemented") } - - Conv::ArmAapcs => sess.dcx().fatal("aapcs call conv not yet implemented"), - Conv::CCmseNonSecureCall => { - sess.dcx().fatal("C-cmse-nonsecure-call call conv is not yet implemented"); - } - Conv::CCmseNonSecureEntry => { - sess.dcx().fatal("C-cmse-nonsecure-entry call conv is not yet implemented"); - } - - Conv::Msp430Intr | Conv::GpuKernel | Conv::AvrInterrupt | Conv::AvrNonBlockingInterrupt => { - unreachable!("tried to use {c:?} call conv which only exists on an unsupported target"); + CanonAbi::GpuKernel => { + unreachable!("tried to use {c:?} call conv which only exists on an unsupported target") } } } @@ -610,7 +605,7 @@ pub(crate) fn codegen_terminator_call<'tcx>( target: CallTarget, call_args: &mut Vec<Value>, ) { - if fn_abi.conv != Conv::C { + if fn_abi.conv != CanonAbi::C { fx.tcx.dcx().span_fatal( source_info.span, format!("Variadic call for non-C abi {:?}", fn_abi.conv), diff --git a/compiler/rustc_codegen_gcc/src/abi.rs b/compiler/rustc_codegen_gcc/src/abi.rs index 0c499ba6237..3d0c258f576 100644 --- a/compiler/rustc_codegen_gcc/src/abi.rs +++ b/compiler/rustc_codegen_gcc/src/abi.rs @@ -1,7 +1,7 @@ #[cfg(feature = "master")] use gccjit::FnAttribute; use gccjit::{ToLValue, ToRValue, Type}; -use rustc_abi::{Reg, RegKind}; +use rustc_abi::{ArmCall, CanonAbi, InterruptKind, Reg, RegKind, X86Call}; use rustc_codegen_ssa::traits::{AbiBuilderMethods, BaseTypeCodegenMethods}; use rustc_data_structures::fx::FxHashSet; use rustc_middle::bug; @@ -10,8 +10,6 @@ use rustc_middle::ty::layout::LayoutOf; #[cfg(feature = "master")] use rustc_session::config; use rustc_target::callconv::{ArgAttributes, CastTarget, FnAbi, PassMode}; -#[cfg(feature = "master")] -use rustc_target::callconv::{Conv, RiscvInterruptKind}; use crate::builder::Builder; use crate::context::CodegenCx; @@ -238,29 +236,16 @@ impl<'gcc, 'tcx> FnAbiGccExt<'gcc, 'tcx> for FnAbi<'tcx, Ty<'tcx>> { } #[cfg(feature = "master")] -pub fn conv_to_fn_attribute<'gcc>(conv: Conv, arch: &str) -> Option<FnAttribute<'gcc>> { +pub fn conv_to_fn_attribute<'gcc>(conv: CanonAbi, arch: &str) -> Option<FnAttribute<'gcc>> { let attribute = match conv { - Conv::C | Conv::Rust => return None, - Conv::CCmseNonSecureCall => { - if arch == "arm" { - FnAttribute::ArmCmseNonsecureCall - } else { - return None; - } - } - Conv::CCmseNonSecureEntry => { - if arch == "arm" { - FnAttribute::ArmCmseNonsecureEntry - } else { - return None; - } - } - Conv::Cold => FnAttribute::Cold, - // NOTE: the preserve attributes are not yet implemented in GCC: - // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110899 - Conv::PreserveMost => return None, - Conv::PreserveAll => return None, - Conv::GpuKernel => { + CanonAbi::C | CanonAbi::Rust => return None, + CanonAbi::Arm(arm_call) => match arm_call { + ArmCall::CCmseNonSecureCall => FnAttribute::ArmCmseNonsecureCall, + ArmCall::CCmseNonSecureEntry => FnAttribute::ArmCmseNonsecureEntry, + ArmCall::Aapcs => FnAttribute::ArmPcs("aapcs"), + }, + CanonAbi::RustCold => FnAttribute::Cold, + CanonAbi::GpuKernel => { if arch == "amdgpu" { FnAttribute::GcnAmdGpuHsaKernel } else if arch == "nvptx64" { @@ -270,26 +255,24 @@ pub fn conv_to_fn_attribute<'gcc>(conv: Conv, arch: &str) -> Option<FnAttribute< } } // TODO(antoyo): check if those AVR attributes are mapped correctly. - Conv::AvrInterrupt => FnAttribute::AvrSignal, - Conv::AvrNonBlockingInterrupt => FnAttribute::AvrInterrupt, - Conv::ArmAapcs => FnAttribute::ArmPcs("aapcs"), - Conv::Msp430Intr => FnAttribute::Msp430Interrupt, - Conv::RiscvInterrupt { kind } => { - let kind = match kind { - RiscvInterruptKind::Machine => "machine", - RiscvInterruptKind::Supervisor => "supervisor", - }; - FnAttribute::RiscvInterrupt(kind) - } - Conv::X86Fastcall => FnAttribute::X86FastCall, - Conv::X86Intr => FnAttribute::X86Interrupt, - Conv::X86Stdcall => FnAttribute::X86Stdcall, - Conv::X86ThisCall => FnAttribute::X86ThisCall, - // NOTE: the vectorcall calling convention is not yet implemented in GCC: - // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89485 - Conv::X86VectorCall => return None, - Conv::X86_64SysV => FnAttribute::X86SysvAbi, - Conv::X86_64Win64 => FnAttribute::X86MsAbi, + CanonAbi::Interrupt(interrupt_kind) => match interrupt_kind { + InterruptKind::Avr => FnAttribute::AvrSignal, + InterruptKind::AvrNonBlocking => FnAttribute::AvrInterrupt, + InterruptKind::Msp430 => FnAttribute::Msp430Interrupt, + InterruptKind::RiscvMachine => FnAttribute::RiscvInterrupt("machine"), + InterruptKind::RiscvSupervisor => FnAttribute::RiscvInterrupt("supervisor"), + InterruptKind::X86 => FnAttribute::X86Interrupt, + }, + CanonAbi::X86(x86_call) => match x86_call { + X86Call::Fastcall => FnAttribute::X86FastCall, + X86Call::Stdcall => FnAttribute::X86Stdcall, + X86Call::Thiscall => FnAttribute::X86ThisCall, + // // NOTE: the vectorcall calling convention is not yet implemented in GCC: + // // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89485 + X86Call::Vectorcall => return None, + X86Call::SysV64 => FnAttribute::X86SysvAbi, + X86Call::Win64 => FnAttribute::X86MsAbi, + }, }; Some(attribute) } diff --git a/compiler/rustc_codegen_gcc/src/int.rs b/compiler/rustc_codegen_gcc/src/int.rs index 9b5b0fde6e2..eb4acd8ade9 100644 --- a/compiler/rustc_codegen_gcc/src/int.rs +++ b/compiler/rustc_codegen_gcc/src/int.rs @@ -3,11 +3,11 @@ //! 128-bit integers on 32-bit platforms and thus require to be handled manually. use gccjit::{BinaryOp, ComparisonOp, FunctionType, Location, RValue, ToRValue, Type, UnaryOp}; -use rustc_abi::{Endian, ExternAbi}; +use rustc_abi::{CanonAbi, Endian, ExternAbi}; use rustc_codegen_ssa::common::{IntPredicate, TypeKind}; use rustc_codegen_ssa::traits::{BackendTypes, BaseTypeCodegenMethods, BuilderMethods, OverflowOp}; use rustc_middle::ty::{self, Ty}; -use rustc_target::callconv::{ArgAbi, ArgAttributes, Conv, FnAbi, PassMode}; +use rustc_target::callconv::{ArgAbi, ArgAttributes, FnAbi, PassMode}; use crate::builder::{Builder, ToGccComp}; use crate::common::{SignType, TypeReflection}; @@ -397,7 +397,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { ret: arg_abi, c_variadic: false, fixed_count: 3, - conv: Conv::C, + conv: CanonAbi::C, can_unwind: false, }; fn_abi.adjust_for_foreign_abi(self.cx, ExternAbi::C { unwind: false }); diff --git a/compiler/rustc_codegen_llvm/src/abi.rs b/compiler/rustc_codegen_llvm/src/abi.rs index c87e70864e5..119cd634f98 100644 --- a/compiler/rustc_codegen_llvm/src/abi.rs +++ b/compiler/rustc_codegen_llvm/src/abi.rs @@ -2,7 +2,10 @@ use std::borrow::Borrow; use std::cmp; use libc::c_uint; -use rustc_abi::{BackendRepr, HasDataLayout, Primitive, Reg, RegKind, Size}; +use rustc_abi::{ + ArmCall, BackendRepr, CanonAbi, HasDataLayout, InterruptKind, Primitive, Reg, RegKind, Size, + X86Call, +}; use rustc_codegen_ssa::MemFlags; use rustc_codegen_ssa::mir::operand::{OperandRef, OperandValue}; use rustc_codegen_ssa::mir::place::{PlaceRef, PlaceValue}; @@ -12,7 +15,7 @@ use rustc_middle::ty::layout::LayoutOf; use rustc_middle::{bug, ty}; use rustc_session::config; use rustc_target::callconv::{ - ArgAbi, ArgAttribute, ArgAttributes, ArgExtension, CastTarget, Conv, FnAbi, PassMode, + ArgAbi, ArgAttribute, ArgAttributes, ArgExtension, CastTarget, FnAbi, PassMode, }; use rustc_target::spec::SanitizerSet; use smallvec::SmallVec; @@ -409,11 +412,17 @@ impl<'ll, 'tcx> FnAbiLlvmExt<'ll, 'tcx> for FnAbi<'tcx, Ty<'tcx>> { if !self.can_unwind { func_attrs.push(llvm::AttributeKind::NoUnwind.create_attr(cx.llcx)); } - if let Conv::RiscvInterrupt { kind } = self.conv { - func_attrs.push(llvm::CreateAttrStringValue(cx.llcx, "interrupt", kind.as_str())); - } - if let Conv::CCmseNonSecureEntry = self.conv { - func_attrs.push(llvm::CreateAttrString(cx.llcx, "cmse_nonsecure_entry")) + match self.conv { + CanonAbi::Interrupt(InterruptKind::RiscvMachine) => { + func_attrs.push(llvm::CreateAttrStringValue(cx.llcx, "interrupt", "machine")) + } + CanonAbi::Interrupt(InterruptKind::RiscvSupervisor) => { + func_attrs.push(llvm::CreateAttrStringValue(cx.llcx, "interrupt", "supervisor")) + } + CanonAbi::Arm(ArmCall::CCmseNonSecureEntry) => { + func_attrs.push(llvm::CreateAttrString(cx.llcx, "cmse_nonsecure_entry")) + } + _ => (), } attributes::apply_to_llfn(llfn, llvm::AttributePlace::Function, &{ func_attrs }); @@ -600,7 +609,7 @@ impl<'ll, 'tcx> FnAbiLlvmExt<'ll, 'tcx> for FnAbi<'tcx, Ty<'tcx>> { llvm::SetInstructionCallConv(callsite, cconv); } - if self.conv == Conv::CCmseNonSecureCall { + if self.conv == CanonAbi::Arm(ArmCall::CCmseNonSecureCall) { // This will probably get ignored on all targets but those supporting the TrustZone-M // extension (thumbv8m targets). let cmse_nonsecure_call = llvm::CreateAttrString(bx.cx.llcx, "cmse_nonsecure_call"); @@ -636,17 +645,11 @@ impl AbiBuilderMethods for Builder<'_, '_, '_> { } impl llvm::CallConv { - pub(crate) fn from_conv(conv: Conv, arch: &str) -> Self { + pub(crate) fn from_conv(conv: CanonAbi, arch: &str) -> Self { match conv { - Conv::C - | Conv::Rust - | Conv::CCmseNonSecureCall - | Conv::CCmseNonSecureEntry - | Conv::RiscvInterrupt { .. } => llvm::CCallConv, - Conv::Cold => llvm::ColdCallConv, - Conv::PreserveMost => llvm::PreserveMost, - Conv::PreserveAll => llvm::PreserveAll, - Conv::GpuKernel => { + CanonAbi::C | CanonAbi::Rust => llvm::CCallConv, + CanonAbi::RustCold => llvm::PreserveMost, + CanonAbi::GpuKernel => { if arch == "amdgpu" { llvm::AmdgpuKernel } else if arch == "nvptx64" { @@ -655,17 +658,25 @@ impl llvm::CallConv { panic!("Architecture {arch} does not support GpuKernel calling convention"); } } - Conv::AvrInterrupt => llvm::AvrInterrupt, - Conv::AvrNonBlockingInterrupt => llvm::AvrNonBlockingInterrupt, - Conv::ArmAapcs => llvm::ArmAapcsCallConv, - Conv::Msp430Intr => llvm::Msp430Intr, - Conv::X86Fastcall => llvm::X86FastcallCallConv, - Conv::X86Intr => llvm::X86_Intr, - Conv::X86Stdcall => llvm::X86StdcallCallConv, - Conv::X86ThisCall => llvm::X86_ThisCall, - Conv::X86VectorCall => llvm::X86_VectorCall, - Conv::X86_64SysV => llvm::X86_64_SysV, - Conv::X86_64Win64 => llvm::X86_64_Win64, + CanonAbi::Interrupt(interrupt_kind) => match interrupt_kind { + InterruptKind::Avr => llvm::AvrInterrupt, + InterruptKind::AvrNonBlocking => llvm::AvrNonBlockingInterrupt, + InterruptKind::Msp430 => llvm::Msp430Intr, + InterruptKind::RiscvMachine | InterruptKind::RiscvSupervisor => llvm::CCallConv, + InterruptKind::X86 => llvm::X86_Intr, + }, + CanonAbi::Arm(arm_call) => match arm_call { + ArmCall::Aapcs => llvm::ArmAapcsCallConv, + ArmCall::CCmseNonSecureCall | ArmCall::CCmseNonSecureEntry => llvm::CCallConv, + }, + CanonAbi::X86(x86_call) => match x86_call { + X86Call::Fastcall => llvm::X86FastcallCallConv, + X86Call::Stdcall => llvm::X86StdcallCallConv, + X86Call::SysV64 => llvm::X86_64_SysV, + X86Call::Thiscall => llvm::X86_ThisCall, + X86Call::Vectorcall => llvm::X86_VectorCall, + X86Call::Win64 => llvm::X86_64_Win64, + }, } } } diff --git a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs index e26f999773d..92b9b6e132e 100644 --- a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs +++ b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs @@ -1,5 +1,6 @@ use std::collections::hash_map::Entry::*; +use rustc_abi::{CanonAbi, X86Call}; use rustc_ast::expand::allocator::{ALLOCATOR_METHODS, NO_ALLOC_SHIM_IS_UNSTABLE, global_fn_name}; use rustc_data_structures::unord::UnordMap; use rustc_hir::def::DefKind; @@ -14,7 +15,6 @@ use rustc_middle::ty::{self, GenericArgKind, GenericArgsRef, Instance, SymbolNam use rustc_middle::util::Providers; use rustc_session::config::{CrateType, OomStrategy}; use rustc_symbol_mangling::mangle_internal_symbol; -use rustc_target::callconv::Conv; use rustc_target::spec::{SanitizerSet, TlsModel}; use tracing::debug; @@ -652,7 +652,7 @@ pub(crate) fn symbol_name_for_instance_in_crate<'tcx>( fn calling_convention_for_symbol<'tcx>( tcx: TyCtxt<'tcx>, symbol: ExportedSymbol<'tcx>, -) -> (Conv, &'tcx [rustc_target::callconv::ArgAbi<'tcx, Ty<'tcx>>]) { +) -> (CanonAbi, &'tcx [rustc_target::callconv::ArgAbi<'tcx, Ty<'tcx>>]) { let instance = match symbol { ExportedSymbol::NonGeneric(def_id) | ExportedSymbol::Generic(def_id, _) if tcx.is_static(def_id) => @@ -683,7 +683,7 @@ fn calling_convention_for_symbol<'tcx>( }) .map(|fnabi| (fnabi.conv, &fnabi.args[..])) // FIXME(workingjubilee): why don't we know the convention here? - .unwrap_or((Conv::Rust, &[])) + .unwrap_or((CanonAbi::Rust, &[])) } /// This is the symbol name of the given instance as seen by the linker. @@ -717,14 +717,14 @@ pub(crate) fn linking_symbol_name_for_instance_in_crate<'tcx>( _ => return undecorated, }; - let (conv, args) = calling_convention_for_symbol(tcx, symbol); + let (callconv, args) = calling_convention_for_symbol(tcx, symbol); // Decorate symbols with prefixes, suffixes and total number of bytes of arguments. // Reference: https://docs.microsoft.com/en-us/cpp/build/reference/decorated-names?view=msvc-170 - let (prefix, suffix) = match conv { - Conv::X86Fastcall => ("@", "@"), - Conv::X86Stdcall => ("_", "@"), - Conv::X86VectorCall => ("", "@@"), + let (prefix, suffix) = match callconv { + CanonAbi::X86(X86Call::Fastcall) => ("@", "@"), + CanonAbi::X86(X86Call::Stdcall) => ("_", "@"), + CanonAbi::X86(X86Call::Vectorcall) => ("", "@@"), _ => { if let Some(prefix) = prefix { undecorated.insert(0, prefix); @@ -758,9 +758,9 @@ pub(crate) fn extend_exported_symbols<'tcx>( symbol: ExportedSymbol<'tcx>, instantiating_crate: CrateNum, ) { - let (conv, _) = calling_convention_for_symbol(tcx, symbol); + let (callconv, _) = calling_convention_for_symbol(tcx, symbol); - if conv != Conv::GpuKernel || tcx.sess.target.os != "amdhsa" { + if callconv != CanonAbi::GpuKernel || tcx.sess.target.os != "amdhsa" { return; } diff --git a/compiler/rustc_const_eval/messages.ftl b/compiler/rustc_const_eval/messages.ftl index 7d4afc9d3d9..5bce6fb7ab2 100644 --- a/compiler/rustc_const_eval/messages.ftl +++ b/compiler/rustc_const_eval/messages.ftl @@ -89,9 +89,9 @@ const_eval_dyn_call_not_a_method = `dyn` call trying to call something that is not a method const_eval_error = {$error_kind -> - [static] could not evaluate static initializer - [const] evaluation of constant value failed - [const_with_path] evaluation of `{$instance}` failed + [static] evaluation of static initializer failed here + [const] evaluation of constant value failed here + [const_with_path] evaluation of `{$instance}` failed here *[other] {""} } @@ -118,7 +118,7 @@ const_eval_frame_note_inner = inside {$where_ -> const_eval_frame_note_last = the failure occurred here const_eval_incompatible_calling_conventions = - calling a function with calling convention {$callee_conv} using calling convention {$caller_conv} + calling a function with calling convention "{$callee_conv}" using calling convention "{$caller_conv}" const_eval_incompatible_return_types = calling a function with return type {$callee_ty} passing return place of type {$caller_ty} diff --git a/compiler/rustc_const_eval/src/check_consts/check.rs b/compiler/rustc_const_eval/src/check_consts/check.rs index b67a3ce03a9..6167f8cd4b5 100644 --- a/compiler/rustc_const_eval/src/check_consts/check.rs +++ b/compiler/rustc_const_eval/src/check_consts/check.rs @@ -589,12 +589,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { Rvalue::Aggregate(kind, ..) => { if let AggregateKind::Coroutine(def_id, ..) = kind.as_ref() - && let Some( - coroutine_kind @ hir::CoroutineKind::Desugared( - hir::CoroutineDesugaring::Async, - _, - ), - ) = self.tcx.coroutine_kind(def_id) + && let Some(coroutine_kind) = self.tcx.coroutine_kind(def_id) { self.check_op(ops::Coroutine(coroutine_kind)); } diff --git a/compiler/rustc_const_eval/src/check_consts/ops.rs b/compiler/rustc_const_eval/src/check_consts/ops.rs index 177ba56b165..d701646719a 100644 --- a/compiler/rustc_const_eval/src/check_consts/ops.rs +++ b/compiler/rustc_const_eval/src/check_consts/ops.rs @@ -486,24 +486,25 @@ impl<'tcx> NonConstOp<'tcx> for IntrinsicUnstable { pub(crate) struct Coroutine(pub hir::CoroutineKind); impl<'tcx> NonConstOp<'tcx> for Coroutine { fn status_in_item(&self, _: &ConstCx<'_, 'tcx>) -> Status { - if let hir::CoroutineKind::Desugared( - hir::CoroutineDesugaring::Async, - hir::CoroutineSource::Block, - ) = self.0 - { - Status::Unstable { + match self.0 { + hir::CoroutineKind::Desugared( + hir::CoroutineDesugaring::Async, + hir::CoroutineSource::Block, + ) + // FIXME(coroutines): eventually we want to gate const coroutine coroutines behind a + // different feature. + | hir::CoroutineKind::Coroutine(_) => Status::Unstable { gate: sym::const_async_blocks, gate_already_checked: false, safe_to_expose_on_stable: false, is_function_call: false, - } - } else { - Status::Forbidden + }, + _ => Status::Forbidden, } } fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> Diag<'tcx> { - let msg = format!("{:#}s are not allowed in {}s", self.0, ccx.const_kind()); + let msg = format!("{} are not allowed in {}s", self.0.to_plural_string(), ccx.const_kind()); if let Status::Unstable { gate, .. } = self.status_in_item(ccx) { ccx.tcx.sess.create_feature_err(errors::UnallowedOpInConstContext { span, msg }, gate) } else { diff --git a/compiler/rustc_const_eval/src/const_eval/error.rs b/compiler/rustc_const_eval/src/const_eval/error.rs index ffb32fa41eb..08fc03d9c46 100644 --- a/compiler/rustc_const_eval/src/const_eval/error.rs +++ b/compiler/rustc_const_eval/src/const_eval/error.rs @@ -1,6 +1,6 @@ use std::mem; -use rustc_errors::{DiagArgName, DiagArgValue, DiagMessage, Diagnostic, IntoDiagArg}; +use rustc_errors::{Diag, DiagArgName, DiagArgValue, DiagMessage, IntoDiagArg}; use rustc_middle::mir::AssertKind; use rustc_middle::mir::interpret::{Provenance, ReportedErrorInfo}; use rustc_middle::query::TyCtxtAt; @@ -131,10 +131,10 @@ pub fn get_span_and_frames<'tcx>( /// Create a diagnostic for a const eval error. /// -/// This will use the `mk` function for creating the error which will get passed labels according to -/// the `InterpError` and the span and a stacktrace of current execution according to -/// `get_span_and_frames`. -pub(super) fn report<'tcx, C, F, E>( +/// This will use the `mk` function for adding more information to the error. +/// You can use it to add a stacktrace of current execution according to +/// `get_span_and_frames` or just give context on where the const eval error happened. +pub(super) fn report<'tcx, C, F>( tcx: TyCtxt<'tcx>, error: InterpErrorKind<'tcx>, span: Span, @@ -143,8 +143,7 @@ pub(super) fn report<'tcx, C, F, E>( ) -> ErrorHandled where C: FnOnce() -> (Span, Vec<FrameNote>), - F: FnOnce(Span, Vec<FrameNote>) -> E, - E: Diagnostic<'tcx>, + F: FnOnce(&mut Diag<'_>, Span, Vec<FrameNote>), { // Special handling for certain errors match error { @@ -163,8 +162,7 @@ where _ => { let (our_span, frames) = get_span_and_frames(); let span = span.substitute_dummy(our_span); - let err = mk(span, frames); - let mut err = tcx.dcx().create_err(err); + let mut err = tcx.dcx().struct_span_err(our_span, error.diagnostic_message()); // We allow invalid programs in infallible promoteds since invalid layouts can occur // anyway (e.g. due to size overflow). And we allow OOM as that can happen any time. let allowed_in_infallible = matches!( @@ -172,11 +170,9 @@ where InterpErrorKind::ResourceExhaustion(_) | InterpErrorKind::InvalidProgram(_) ); - let msg = error.diagnostic_message(); error.add_args(&mut err); - // Use *our* span to label the interp error - err.span_label(our_span, msg); + mk(&mut err, span, frames); let g = err.emit(); let reported = if allowed_in_infallible { ReportedErrorInfo::allowed_in_infallible(g) diff --git a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs index a79ba6a6342..01625b91353 100644 --- a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs +++ b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs @@ -2,6 +2,7 @@ use std::sync::atomic::Ordering::Relaxed; use either::{Left, Right}; use rustc_abi::{self as abi, BackendRepr}; +use rustc_errors::E0080; use rustc_hir::def::DefKind; use rustc_middle::mir::interpret::{AllocId, ErrorHandled, InterpErrorInfo, ReportedErrorInfo}; use rustc_middle::mir::{self, ConstAlloc, ConstValue}; @@ -290,12 +291,18 @@ pub fn eval_to_const_value_raw_provider<'tcx>( |error| { let span = tcx.def_span(def_id); + // FIXME(oli-obk): why don't we have any tests for this code path? super::report( tcx, error.into_kind(), span, || (span, vec![]), - |span, _| errors::NullaryIntrinsicError { span }, + |diag, span, _| { + diag.span_label( + span, + crate::fluent_generated::const_eval_nullary_intrinsic_fail, + ); + }, ) }, ); @@ -443,11 +450,15 @@ fn report_eval_error<'tcx>( error, DUMMY_SP, || super::get_span_and_frames(ecx.tcx, ecx.stack()), - |span, frames| errors::ConstEvalError { - span, - error_kind: kind, - instance, - frame_notes: frames, + |diag, span, frames| { + // FIXME(oli-obk): figure out how to use structured diagnostics again. + diag.code(E0080); + diag.span_label(span, crate::fluent_generated::const_eval_error); + diag.arg("instance", instance); + diag.arg("error_kind", kind); + for frame in frames { + diag.subdiagnostic(frame); + } }, ) } @@ -477,6 +488,15 @@ fn report_validation_error<'tcx>( error, DUMMY_SP, || crate::const_eval::get_span_and_frames(ecx.tcx, ecx.stack()), - move |span, frames| errors::ValidationFailure { span, ub_note: (), frames, raw_bytes }, + move |diag, span, frames| { + // FIXME(oli-obk): figure out how to use structured diagnostics again. + diag.code(E0080); + diag.span_label(span, crate::fluent_generated::const_eval_validation_failure); + diag.note(crate::fluent_generated::const_eval_validation_failure_note); + for frame in frames { + diag.subdiagnostic(frame); + } + diag.subdiagnostic(raw_bytes); + }, ) } diff --git a/compiler/rustc_const_eval/src/errors.rs b/compiler/rustc_const_eval/src/errors.rs index 7c35e47bbf8..037cbf777e7 100644 --- a/compiler/rustc_const_eval/src/errors.rs +++ b/compiler/rustc_const_eval/src/errors.rs @@ -439,38 +439,6 @@ pub struct LiveDrop<'tcx> { pub dropped_at: Span, } -#[derive(Diagnostic)] -#[diag(const_eval_error, code = E0080)] -pub struct ConstEvalError { - #[primary_span] - pub span: Span, - /// One of "const", "const_with_path", and "static" - pub error_kind: &'static str, - pub instance: String, - #[subdiagnostic] - pub frame_notes: Vec<FrameNote>, -} - -#[derive(Diagnostic)] -#[diag(const_eval_nullary_intrinsic_fail)] -pub struct NullaryIntrinsicError { - #[primary_span] - pub span: Span, -} - -#[derive(Diagnostic)] -#[diag(const_eval_validation_failure, code = E0080)] -pub struct ValidationFailure { - #[primary_span] - pub span: Span, - #[note(const_eval_validation_failure_note)] - pub ub_note: (), - #[subdiagnostic] - pub frames: Vec<FrameNote>, - #[subdiagnostic] - pub raw_bytes: RawBytesNote, -} - pub trait ReportErrorExt { /// Returns the diagnostic message for this error. fn diagnostic_message(&self) -> DiagMessage; diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 4f05e1c816c..433d5f98829 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -2061,12 +2061,19 @@ impl CoroutineKind { CoroutineKind::Coroutine(mov) => mov, } } -} -impl CoroutineKind { pub fn is_fn_like(self) -> bool { matches!(self, CoroutineKind::Desugared(_, CoroutineSource::Fn)) } + + pub fn to_plural_string(&self) -> String { + match self { + CoroutineKind::Desugared(d, CoroutineSource::Fn) => format!("{d:#}fn bodies"), + CoroutineKind::Desugared(d, CoroutineSource::Block) => format!("{d:#}blocks"), + CoroutineKind::Desugared(d, CoroutineSource::Closure) => format!("{d:#}closure bodies"), + CoroutineKind::Coroutine(_) => "coroutines".to_string(), + } + } } impl fmt::Display for CoroutineKind { diff --git a/compiler/rustc_hir_typeck/src/closure.rs b/compiler/rustc_hir_typeck/src/closure.rs index b1cb3ef4d79..cd3746be1d1 100644 --- a/compiler/rustc_hir_typeck/src/closure.rs +++ b/compiler/rustc_hir_typeck/src/closure.rs @@ -204,14 +204,19 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ) } hir::ClosureKind::CoroutineClosure(kind) => { - // async closures always return the type ascribed after the `->` (if present), - // and yield `()`. let (bound_return_ty, bound_yield_ty) = match kind { + hir::CoroutineDesugaring::Gen => { + // `iter!` closures always return unit and yield the `Iterator::Item` type + // that we have to infer. + (tcx.types.unit, self.infcx.next_ty_var(expr_span)) + } hir::CoroutineDesugaring::Async => { + // async closures always return the type ascribed after the `->` (if present), + // and yield `()`. (bound_sig.skip_binder().output(), tcx.types.unit) } - hir::CoroutineDesugaring::Gen | hir::CoroutineDesugaring::AsyncGen => { - todo!("`gen` and `async gen` closures not supported yet") + hir::CoroutineDesugaring::AsyncGen => { + todo!("`async gen` closures not supported yet") } }; // Compute all of the variables that will be used to populate the coroutine. @@ -465,7 +470,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if let Some(trait_def_id) = trait_def_id { let found_kind = match closure_kind { - hir::ClosureKind::Closure => self.tcx.fn_trait_kind_from_def_id(trait_def_id), + hir::ClosureKind::Closure + // FIXME(iter_macro): Someday we'll probably want iterator closures instead of + // just using Fn* for iterators. + | hir::ClosureKind::CoroutineClosure(hir::CoroutineDesugaring::Gen) => { + self.tcx.fn_trait_kind_from_def_id(trait_def_id) + } hir::ClosureKind::CoroutineClosure(hir::CoroutineDesugaring::Async) => self .tcx .async_fn_trait_kind_from_def_id(trait_def_id) diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index 5bc7559d29a..f4045eeea4d 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -60,10 +60,6 @@ pub fn parse<'a>(sess: &'a Session) -> ast::Crate { guar.raise_fatal(); }); - if sess.opts.unstable_opts.input_stats { - input_stats::print_ast_stats(&krate, "PRE EXPANSION AST STATS", "ast-stats-1"); - } - rustc_builtin_macros::cmdline_attrs::inject( &mut krate, &sess.psess, @@ -298,7 +294,7 @@ fn early_lint_checks(tcx: TyCtxt<'_>, (): ()) { let mut lint_buffer = resolver.lint_buffer.steal(); if sess.opts.unstable_opts.input_stats { - input_stats::print_ast_stats(krate, "POST EXPANSION AST STATS", "ast-stats-2"); + input_stats::print_ast_stats(krate, "POST EXPANSION AST STATS", "ast-stats"); } // Needs to go *after* expansion to be able to check the results of macro expansion. diff --git a/compiler/rustc_monomorphize/src/mono_checks/abi_check.rs b/compiler/rustc_monomorphize/src/mono_checks/abi_check.rs index cfeaee07776..5478e54a606 100644 --- a/compiler/rustc_monomorphize/src/mono_checks/abi_check.rs +++ b/compiler/rustc_monomorphize/src/mono_checks/abi_check.rs @@ -1,6 +1,6 @@ //! This module ensures that if a function's ABI requires a particular target feature, //! that target feature is enabled both on the callee and all callers. -use rustc_abi::{BackendRepr, RegKind}; +use rustc_abi::{BackendRepr, CanonAbi, RegKind, X86Call}; use rustc_hir::{CRATE_HIR_ID, HirId}; use rustc_middle::mir::{self, Location, traversal}; use rustc_middle::ty::layout::LayoutCx; @@ -8,7 +8,7 @@ use rustc_middle::ty::{self, Instance, InstanceKind, Ty, TyCtxt, TypingEnv}; use rustc_session::lint::builtin::WASM_C_ABI; use rustc_span::def_id::DefId; use rustc_span::{DUMMY_SP, Span, Symbol, sym}; -use rustc_target::callconv::{ArgAbi, Conv, FnAbi, PassMode}; +use rustc_target::callconv::{ArgAbi, FnAbi, PassMode}; use rustc_target::spec::{HasWasmCAbiOpt, WasmCAbi}; use crate::errors; @@ -72,7 +72,7 @@ fn do_check_simd_vector_abi<'tcx>( } } // The `vectorcall` ABI is special in that it requires SSE2 no matter which types are being passed. - if abi.conv == Conv::X86VectorCall && !have_feature(sym::sse2) { + if abi.conv == CanonAbi::X86(X86Call::Vectorcall) && !have_feature(sym::sse2) { let (span, _hir_id) = loc(); tcx.dcx().emit_err(errors::AbiRequiredTargetFeature { span, @@ -128,7 +128,7 @@ fn do_check_wasm_abi<'tcx>( if !(tcx.sess.target.arch == "wasm32" && tcx.sess.target.os == "unknown" && tcx.wasm_c_abi_opt() == WasmCAbi::Legacy { with_lint: true } - && abi.conv == Conv::C) + && abi.conv == CanonAbi::C) { return; } diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 1a44f4af8a6..adfea3641e6 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -834,7 +834,7 @@ impl<'a> Parser<'a> { // guides recovery in case we write `&raw expr`. if borrow_kind == ast::BorrowKind::Ref && mutbl == ast::Mutability::Not - && matches!(&expr.kind, ExprKind::Path(None, p) if p.is_ident(kw::Raw)) + && matches!(&expr.kind, ExprKind::Path(None, p) if *p == kw::Raw) { self.expected_token_types.insert(TokenType::KwMut); self.expected_token_types.insert(TokenType::KwConst); diff --git a/compiler/rustc_parse/src/parser/stmt.rs b/compiler/rustc_parse/src/parser/stmt.rs index ccc3410674b..c37cb0881c3 100644 --- a/compiler/rustc_parse/src/parser/stmt.rs +++ b/compiler/rustc_parse/src/parser/stmt.rs @@ -713,7 +713,7 @@ impl<'a> Parser<'a> { /// Parses the rest of a block expression or function body. /// Precondition: already parsed the '{'. - pub(crate) fn parse_block_tail( + pub fn parse_block_tail( &mut self, lo: Span, s: BlockCheckMode, diff --git a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/mod.rs b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/mod.rs index 562e288afaa..82e18ad497b 100644 --- a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/mod.rs +++ b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/mod.rs @@ -4,10 +4,11 @@ //! For more information about LLVM CFI and cross-language LLVM CFI support for the Rust compiler, //! see design document in the tracking issue #89653. +use rustc_abi::CanonAbi; use rustc_data_structures::fx::FxHashMap; use rustc_middle::bug; use rustc_middle::ty::{self, Instance, Ty, TyCtxt, TypeFoldable, TypeVisitableExt}; -use rustc_target::callconv::{Conv, FnAbi, PassMode}; +use rustc_target::callconv::{FnAbi, PassMode}; use tracing::instrument; mod encode; @@ -45,7 +46,7 @@ pub fn typeid_for_fnabi<'tcx>( let mut encode_ty_options = EncodeTyOptions::from_bits(options.bits()) .unwrap_or_else(|| bug!("typeid_for_fnabi: invalid option(s) `{:?}`", options.bits())); match fn_abi.conv { - Conv::C => { + CanonAbi::C => { encode_ty_options.insert(EncodeTyOptions::GENERALIZE_REPR_C); } _ => { diff --git a/compiler/rustc_smir/src/rustc_smir/convert/abi.rs b/compiler/rustc_smir/src/rustc_smir/convert/abi.rs index 7ccc785a400..06dfaf079a3 100644 --- a/compiler/rustc_smir/src/rustc_smir/convert/abi.rs +++ b/compiler/rustc_smir/src/rustc_smir/convert/abi.rs @@ -2,8 +2,9 @@ #![allow(rustc::usage_of_qualified_ty)] +use rustc_abi::{ArmCall, CanonAbi, InterruptKind, X86Call}; use rustc_middle::ty; -use rustc_target::callconv::{self, Conv}; +use rustc_target::callconv; use stable_mir::abi::{ AddressSpace, ArgAbi, CallConvention, FieldsShape, FloatLength, FnAbi, IntegerLength, Layout, LayoutShape, PassMode, Primitive, Scalar, TagEncoding, TyAndLayout, ValueAbi, VariantsShape, @@ -69,7 +70,7 @@ impl<'tcx> Stable<'tcx> for callconv::FnAbi<'tcx, ty::Ty<'tcx>> { fn stable(&self, tables: &mut Tables<'_>) -> Self::T { assert!(self.args.len() >= self.fixed_count as usize); - assert!(!self.c_variadic || matches!(self.conv, Conv::C)); + assert!(!self.c_variadic || matches!(self.conv, CanonAbi::C)); FnAbi { args: self.args.as_ref().stable(tables), ret: self.ret.stable(tables), @@ -92,31 +93,37 @@ impl<'tcx> Stable<'tcx> for callconv::ArgAbi<'tcx, ty::Ty<'tcx>> { } } -impl<'tcx> Stable<'tcx> for callconv::Conv { +impl<'tcx> Stable<'tcx> for CanonAbi { type T = CallConvention; fn stable(&self, _tables: &mut Tables<'_>) -> Self::T { match self { - Conv::C => CallConvention::C, - Conv::Rust => CallConvention::Rust, - Conv::Cold => CallConvention::Cold, - Conv::PreserveMost => CallConvention::PreserveMost, - Conv::PreserveAll => CallConvention::PreserveAll, - Conv::ArmAapcs => CallConvention::ArmAapcs, - Conv::CCmseNonSecureCall => CallConvention::CCmseNonSecureCall, - Conv::CCmseNonSecureEntry => CallConvention::CCmseNonSecureEntry, - Conv::Msp430Intr => CallConvention::Msp430Intr, - Conv::X86Fastcall => CallConvention::X86Fastcall, - Conv::X86Intr => CallConvention::X86Intr, - Conv::X86Stdcall => CallConvention::X86Stdcall, - Conv::X86ThisCall => CallConvention::X86ThisCall, - Conv::X86VectorCall => CallConvention::X86VectorCall, - Conv::X86_64SysV => CallConvention::X86_64SysV, - Conv::X86_64Win64 => CallConvention::X86_64Win64, - Conv::GpuKernel => CallConvention::GpuKernel, - Conv::AvrInterrupt => CallConvention::AvrInterrupt, - Conv::AvrNonBlockingInterrupt => CallConvention::AvrNonBlockingInterrupt, - Conv::RiscvInterrupt { .. } => CallConvention::RiscvInterrupt, + CanonAbi::C => CallConvention::C, + CanonAbi::Rust => CallConvention::Rust, + CanonAbi::RustCold => CallConvention::Cold, + CanonAbi::Arm(arm_call) => match arm_call { + ArmCall::Aapcs => CallConvention::ArmAapcs, + ArmCall::CCmseNonSecureCall => CallConvention::CCmseNonSecureCall, + ArmCall::CCmseNonSecureEntry => CallConvention::CCmseNonSecureEntry, + }, + CanonAbi::GpuKernel => CallConvention::GpuKernel, + CanonAbi::Interrupt(interrupt_kind) => match interrupt_kind { + InterruptKind::Avr => CallConvention::AvrInterrupt, + InterruptKind::AvrNonBlocking => CallConvention::AvrNonBlockingInterrupt, + InterruptKind::Msp430 => CallConvention::Msp430Intr, + InterruptKind::RiscvMachine | InterruptKind::RiscvSupervisor => { + CallConvention::RiscvInterrupt + } + InterruptKind::X86 => CallConvention::X86Intr, + }, + CanonAbi::X86(x86_call) => match x86_call { + X86Call::Fastcall => CallConvention::X86Fastcall, + X86Call::Stdcall => CallConvention::X86Stdcall, + X86Call::SysV64 => CallConvention::X86_64SysV, + X86Call::Thiscall => CallConvention::X86ThisCall, + X86Call::Vectorcall => CallConvention::X86VectorCall, + X86Call::Win64 => CallConvention::X86_64Win64, + }, } } } diff --git a/compiler/rustc_target/src/callconv/arm.rs b/compiler/rustc_target/src/callconv/arm.rs index 0a5dcc66347..70830fa07b6 100644 --- a/compiler/rustc_target/src/callconv/arm.rs +++ b/compiler/rustc_target/src/callconv/arm.rs @@ -1,6 +1,6 @@ -use rustc_abi::{HasDataLayout, TyAbiInterface}; +use rustc_abi::{ArmCall, CanonAbi, HasDataLayout, TyAbiInterface}; -use crate::callconv::{ArgAbi, Conv, FnAbi, Reg, RegKind, Uniform}; +use crate::callconv::{ArgAbi, FnAbi, Reg, RegKind, Uniform}; use crate::spec::HasTargetSpec; fn is_homogeneous_aggregate<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>) -> Option<Uniform> @@ -90,7 +90,7 @@ where // If this is a target with a hard-float ABI, and the function is not explicitly // `extern "aapcs"`, then we must use the VFP registers for homogeneous aggregates. let vfp = cx.target_spec().llvm_target.ends_with("hf") - && fn_abi.conv != Conv::ArmAapcs + && fn_abi.conv != CanonAbi::Arm(ArmCall::Aapcs) && !fn_abi.c_variadic; if !fn_abi.ret.is_ignore() { diff --git a/compiler/rustc_target/src/callconv/mod.rs b/compiler/rustc_target/src/callconv/mod.rs index 907614520a2..d2e49cea647 100644 --- a/compiler/rustc_target/src/callconv/mod.rs +++ b/compiler/rustc_target/src/callconv/mod.rs @@ -1,13 +1,12 @@ -use std::fmt::Display; -use std::str::FromStr; use std::{fmt, iter}; use rustc_abi::{ - AddressSpace, Align, BackendRepr, ExternAbi, HasDataLayout, Primitive, Reg, RegKind, Scalar, - Size, TyAbiInterface, TyAndLayout, + AddressSpace, Align, BackendRepr, CanonAbi, ExternAbi, HasDataLayout, Primitive, Reg, RegKind, + Scalar, Size, TyAbiInterface, TyAndLayout, }; use rustc_macros::HashStable_Generic; +pub use crate::spec::AbiMap; use crate::spec::{HasTargetSpec, HasWasmCAbiOpt, HasX86AbiOpt, RustcAbi, WasmCAbi}; mod aarch64; @@ -530,41 +529,6 @@ impl<'a, Ty> ArgAbi<'a, Ty> { } #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, HashStable_Generic)] -pub enum Conv { - // General language calling conventions, for which every target - // should have its own backend (e.g. LLVM) support. - C, - Rust, - - Cold, - PreserveMost, - PreserveAll, - - // Target-specific calling conventions. - ArmAapcs, - CCmseNonSecureCall, - CCmseNonSecureEntry, - - Msp430Intr, - - GpuKernel, - - X86Fastcall, - X86Intr, - X86Stdcall, - X86ThisCall, - X86VectorCall, - - X86_64SysV, - X86_64Win64, - - AvrInterrupt, - AvrNonBlockingInterrupt, - - RiscvInterrupt { kind: RiscvInterruptKind }, -} - -#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, HashStable_Generic)] pub enum RiscvInterruptKind { Machine, Supervisor, @@ -605,7 +569,7 @@ pub struct FnAbi<'a, Ty> { /// This can be used to know whether an argument is variadic or not. pub fixed_count: u32, /// The calling convention of this function. - pub conv: Conv, + pub conv: CanonAbi, /// Indicates if an unwind may happen across a call to this function. pub can_unwind: bool, } @@ -696,7 +660,6 @@ impl<'a, Ty> FnAbi<'a, Ty> { "sparc" => sparc::compute_abi_info(cx, self), "sparc64" => sparc64::compute_abi_info(cx, self), "nvptx64" => { - let abi = cx.target_spec().adjust_abi(abi, self.c_variadic); if abi == ExternAbi::PtxKernel || abi == ExternAbi::GpuKernel { nvptx64::compute_ptx_kernel_abi_info(cx, self) } else { @@ -863,70 +826,6 @@ impl<'a, Ty> FnAbi<'a, Ty> { } } -impl FromStr for Conv { - type Err = String; - - fn from_str(s: &str) -> Result<Self, Self::Err> { - match s { - "C" => Ok(Conv::C), - "Rust" => Ok(Conv::Rust), - "RustCold" => Ok(Conv::Rust), - "ArmAapcs" => Ok(Conv::ArmAapcs), - "CCmseNonSecureCall" => Ok(Conv::CCmseNonSecureCall), - "CCmseNonSecureEntry" => Ok(Conv::CCmseNonSecureEntry), - "Msp430Intr" => Ok(Conv::Msp430Intr), - "X86Fastcall" => Ok(Conv::X86Fastcall), - "X86Intr" => Ok(Conv::X86Intr), - "X86Stdcall" => Ok(Conv::X86Stdcall), - "X86ThisCall" => Ok(Conv::X86ThisCall), - "X86VectorCall" => Ok(Conv::X86VectorCall), - "X86_64SysV" => Ok(Conv::X86_64SysV), - "X86_64Win64" => Ok(Conv::X86_64Win64), - "GpuKernel" => Ok(Conv::GpuKernel), - "AvrInterrupt" => Ok(Conv::AvrInterrupt), - "AvrNonBlockingInterrupt" => Ok(Conv::AvrNonBlockingInterrupt), - "RiscvInterrupt(machine)" => { - Ok(Conv::RiscvInterrupt { kind: RiscvInterruptKind::Machine }) - } - "RiscvInterrupt(supervisor)" => { - Ok(Conv::RiscvInterrupt { kind: RiscvInterruptKind::Supervisor }) - } - _ => Err(format!("'{s}' is not a valid value for entry function call convention.")), - } - } -} - -fn conv_to_externabi(conv: &Conv) -> ExternAbi { - match conv { - Conv::C => ExternAbi::C { unwind: false }, - Conv::Rust => ExternAbi::Rust, - Conv::PreserveMost => ExternAbi::RustCold, - Conv::ArmAapcs => ExternAbi::Aapcs { unwind: false }, - Conv::CCmseNonSecureCall => ExternAbi::CCmseNonSecureCall, - Conv::CCmseNonSecureEntry => ExternAbi::CCmseNonSecureEntry, - Conv::Msp430Intr => ExternAbi::Msp430Interrupt, - Conv::GpuKernel => ExternAbi::GpuKernel, - Conv::X86Fastcall => ExternAbi::Fastcall { unwind: false }, - Conv::X86Intr => ExternAbi::X86Interrupt, - Conv::X86Stdcall => ExternAbi::Stdcall { unwind: false }, - Conv::X86ThisCall => ExternAbi::Thiscall { unwind: false }, - Conv::X86VectorCall => ExternAbi::Vectorcall { unwind: false }, - Conv::X86_64SysV => ExternAbi::SysV64 { unwind: false }, - Conv::X86_64Win64 => ExternAbi::Win64 { unwind: false }, - Conv::AvrInterrupt => ExternAbi::AvrInterrupt, - Conv::AvrNonBlockingInterrupt => ExternAbi::AvrNonBlockingInterrupt, - Conv::RiscvInterrupt { kind: RiscvInterruptKind::Machine } => ExternAbi::RiscvInterruptM, - Conv::RiscvInterrupt { kind: RiscvInterruptKind::Supervisor } => ExternAbi::RiscvInterruptS, - Conv::Cold | Conv::PreserveAll => unreachable!(), - } -} - -impl Display for Conv { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "{}", conv_to_externabi(self)) - } -} - // Some types are used a lot. Make sure they don't unintentionally get bigger. #[cfg(target_pointer_width = "64")] mod size_asserts { diff --git a/compiler/rustc_target/src/json.rs b/compiler/rustc_target/src/json.rs index 8d6f8f4c6f6..4fcc477921b 100644 --- a/compiler/rustc_target/src/json.rs +++ b/compiler/rustc_target/src/json.rs @@ -92,38 +92,6 @@ impl<A: ToJson> ToJson for Option<A> { } } -impl ToJson for crate::callconv::Conv { - fn to_json(&self) -> Json { - let buf: String; - let s = match self { - Self::C => "C", - Self::Rust => "Rust", - Self::Cold => "Cold", - Self::PreserveMost => "PreserveMost", - Self::PreserveAll => "PreserveAll", - Self::ArmAapcs => "ArmAapcs", - Self::CCmseNonSecureCall => "CCmseNonSecureCall", - Self::CCmseNonSecureEntry => "CCmseNonSecureEntry", - Self::Msp430Intr => "Msp430Intr", - Self::X86Fastcall => "X86Fastcall", - Self::X86Intr => "X86Intr", - Self::X86Stdcall => "X86Stdcall", - Self::X86ThisCall => "X86ThisCall", - Self::X86VectorCall => "X86VectorCall", - Self::X86_64SysV => "X86_64SysV", - Self::X86_64Win64 => "X86_64Win64", - Self::GpuKernel => "GpuKernel", - Self::AvrInterrupt => "AvrInterrupt", - Self::AvrNonBlockingInterrupt => "AvrNonBlockingInterrupt", - Self::RiscvInterrupt { kind } => { - buf = format!("RiscvInterrupt({})", kind.as_str()); - &buf - } - }; - Json::String(s.to_owned()) - } -} - impl ToJson for TargetMetadata { fn to_json(&self) -> Json { json!({ @@ -140,3 +108,9 @@ impl ToJson for rustc_abi::Endian { self.as_str().to_json() } } + +impl ToJson for rustc_abi::CanonAbi { + fn to_json(&self) -> Json { + self.to_string().to_json() + } +} diff --git a/compiler/rustc_target/src/spec/abi_map.rs b/compiler/rustc_target/src/spec/abi_map.rs new file mode 100644 index 00000000000..d9101f79f04 --- /dev/null +++ b/compiler/rustc_target/src/spec/abi_map.rs @@ -0,0 +1,187 @@ +use rustc_abi::{ArmCall, CanonAbi, ExternAbi, InterruptKind, X86Call}; + +use crate::spec::Target; + +/// Mapping for ExternAbi to CanonAbi according to a Target +/// +/// A maybe-transitional structure circa 2025 for hosting future experiments in +/// encapsulating arch-specific ABI lowering details to make them more testable. +#[derive(Clone, Debug)] +pub struct AbiMap { + arch: Arch, + os: OsKind, +} + +#[derive(Copy, Clone, Debug)] +pub enum AbiMapping { + /// this ABI is exactly mapped for this platform + Direct(CanonAbi), + /// we don't yet warn on this, but we will + Deprecated(CanonAbi), + Invalid, +} + +impl AbiMapping { + pub fn into_option(self) -> Option<CanonAbi> { + match self { + Self::Direct(abi) | Self::Deprecated(abi) => Some(abi), + Self::Invalid => None, + } + } + + pub fn unwrap(self) -> CanonAbi { + self.into_option().unwrap() + } + + pub fn is_mapped(self) -> bool { + self.into_option().is_some() + } +} + +impl AbiMap { + pub fn from_target(target: &Target) -> Self { + // the purpose of this little exercise is to force listing what affects these mappings + let arch = match &*target.arch { + "aarch64" => Arch::Aarch64, + "amdgpu" => Arch::Amdgpu, + "arm" if target.llvm_target.starts_with("thumbv8m") => Arch::Arm(ArmVer::ThumbV8M), + "arm" => Arch::Arm(ArmVer::Other), + "avr" => Arch::Avr, + "msp430" => Arch::Msp430, + "nvptx64" => Arch::Nvptx, + "riscv32" | "riscv64" => Arch::Riscv, + "x86" => Arch::X86, + "x86_64" => Arch::X86_64, + _ => Arch::Other, + }; + let os = if target.is_like_windows { OsKind::Windows } else { OsKind::Other }; + AbiMap { arch, os } + } + + pub fn canonize_abi(&self, extern_abi: ExternAbi, has_c_varargs: bool) -> AbiMapping { + let AbiMap { os, arch } = *self; + + let canon_abi = match (extern_abi, arch) { + // infallible lowerings + (ExternAbi::C { .. }, _) => CanonAbi::C, + (ExternAbi::Rust | ExternAbi::RustCall, _) => CanonAbi::Rust, + (ExternAbi::Unadjusted, _) => CanonAbi::C, + + (ExternAbi::RustCold, _) if self.os == OsKind::Windows => CanonAbi::Rust, + (ExternAbi::RustCold, _) => CanonAbi::RustCold, + + (ExternAbi::System { .. }, Arch::X86) if os == OsKind::Windows && !has_c_varargs => { + CanonAbi::X86(X86Call::Stdcall) + } + (ExternAbi::System { .. }, _) => CanonAbi::C, + + // fallible lowerings + (ExternAbi::EfiApi, Arch::Arm(..)) => CanonAbi::Arm(ArmCall::Aapcs), + (ExternAbi::EfiApi, Arch::X86_64) => CanonAbi::X86(X86Call::Win64), + (ExternAbi::EfiApi, Arch::Aarch64 | Arch::Riscv | Arch::X86) => CanonAbi::C, + (ExternAbi::EfiApi, _) => return AbiMapping::Invalid, + + (ExternAbi::Aapcs { .. }, Arch::Arm(..)) => CanonAbi::Arm(ArmCall::Aapcs), + (ExternAbi::Aapcs { .. }, _) => return AbiMapping::Invalid, + + (ExternAbi::CCmseNonSecureCall, Arch::Arm(ArmVer::ThumbV8M)) => { + CanonAbi::Arm(ArmCall::CCmseNonSecureCall) + } + (ExternAbi::CCmseNonSecureEntry, Arch::Arm(ArmVer::ThumbV8M)) => { + CanonAbi::Arm(ArmCall::CCmseNonSecureEntry) + } + (ExternAbi::CCmseNonSecureCall | ExternAbi::CCmseNonSecureEntry, ..) => { + return AbiMapping::Invalid; + } + + (ExternAbi::Cdecl { .. }, Arch::X86) => CanonAbi::C, + (ExternAbi::Cdecl { .. }, _) => return AbiMapping::Deprecated(CanonAbi::C), + + (ExternAbi::Fastcall { .. }, Arch::X86) => CanonAbi::X86(X86Call::Fastcall), + (ExternAbi::Fastcall { .. }, _) if os == OsKind::Windows => { + return AbiMapping::Deprecated(CanonAbi::C); + } + (ExternAbi::Fastcall { .. }, _) => return AbiMapping::Invalid, + + (ExternAbi::Stdcall { .. }, Arch::X86) => CanonAbi::X86(X86Call::Stdcall), + (ExternAbi::Stdcall { .. }, _) if os == OsKind::Windows => { + return AbiMapping::Deprecated(CanonAbi::C); + } + (ExternAbi::Stdcall { .. }, _) => return AbiMapping::Invalid, + + (ExternAbi::Thiscall { .. }, Arch::X86) => CanonAbi::X86(X86Call::Thiscall), + (ExternAbi::Thiscall { .. }, _) => return AbiMapping::Invalid, + + (ExternAbi::Vectorcall { .. }, Arch::X86 | Arch::X86_64) => { + CanonAbi::X86(X86Call::Vectorcall) + } + (ExternAbi::Vectorcall { .. }, _) if os == OsKind::Windows => { + return AbiMapping::Deprecated(CanonAbi::C); + } + (ExternAbi::Vectorcall { .. }, _) => return AbiMapping::Invalid, + + (ExternAbi::SysV64 { .. }, Arch::X86_64) => CanonAbi::X86(X86Call::SysV64), + (ExternAbi::Win64 { .. }, Arch::X86_64) => CanonAbi::X86(X86Call::Win64), + (ExternAbi::SysV64 { .. } | ExternAbi::Win64 { .. }, _) => return AbiMapping::Invalid, + + (ExternAbi::PtxKernel, Arch::Nvptx) => CanonAbi::GpuKernel, + (ExternAbi::GpuKernel, Arch::Amdgpu | Arch::Nvptx) => CanonAbi::GpuKernel, + (ExternAbi::PtxKernel | ExternAbi::GpuKernel, _) => return AbiMapping::Invalid, + + (ExternAbi::AvrInterrupt, Arch::Avr) => CanonAbi::Interrupt(InterruptKind::Avr), + (ExternAbi::AvrNonBlockingInterrupt, Arch::Avr) => { + CanonAbi::Interrupt(InterruptKind::AvrNonBlocking) + } + (ExternAbi::Msp430Interrupt, Arch::Msp430) => { + CanonAbi::Interrupt(InterruptKind::Msp430) + } + (ExternAbi::RiscvInterruptM, Arch::Riscv) => { + CanonAbi::Interrupt(InterruptKind::RiscvMachine) + } + (ExternAbi::RiscvInterruptS, Arch::Riscv) => { + CanonAbi::Interrupt(InterruptKind::RiscvSupervisor) + } + (ExternAbi::X86Interrupt, Arch::X86 | Arch::X86_64) => { + CanonAbi::Interrupt(InterruptKind::X86) + } + ( + ExternAbi::AvrInterrupt + | ExternAbi::AvrNonBlockingInterrupt + | ExternAbi::Msp430Interrupt + | ExternAbi::RiscvInterruptM + | ExternAbi::RiscvInterruptS + | ExternAbi::X86Interrupt, + _, + ) => return AbiMapping::Invalid, + }; + + AbiMapping::Direct(canon_abi) + } +} + +#[derive(Debug, PartialEq, Copy, Clone)] +enum Arch { + Aarch64, + Amdgpu, + Arm(ArmVer), + Avr, + Msp430, + Nvptx, + Riscv, + X86, + X86_64, + /// Architectures which don't need other considerations for ABI lowering + Other, +} + +#[derive(Debug, PartialEq, Copy, Clone)] +enum OsKind { + Windows, + Other, +} + +#[derive(Debug, PartialEq, Copy, Clone)] +enum ArmVer { + ThumbV8M, + Other, +} diff --git a/compiler/rustc_target/src/spec/json.rs b/compiler/rustc_target/src/spec/json.rs index be71da76b4a..54b06d9f9b4 100644 --- a/compiler/rustc_target/src/spec/json.rs +++ b/compiler/rustc_target/src/spec/json.rs @@ -2,10 +2,12 @@ use std::borrow::Cow; use std::collections::BTreeMap; use std::str::FromStr; +use rustc_abi::ExternAbi; use serde_json::Value; use super::{Target, TargetKind, TargetOptions, TargetWarnings}; use crate::json::{Json, ToJson}; +use crate::spec::AbiMap; impl Target { /// Loads a target descriptor from a JSON object. @@ -515,18 +517,6 @@ impl Target { } } } ); - ($key_name:ident, Conv) => ( { - let name = (stringify!($key_name)).replace("_", "-"); - obj.remove(&name).and_then(|o| o.as_str().and_then(|s| { - match super::Conv::from_str(s) { - Ok(c) => { - base.$key_name = c; - Some(Ok(())) - } - Err(e) => Some(Err(e)) - } - })).unwrap_or(Ok(())) - } ); } if let Some(j) = obj.remove("target-endian") { @@ -660,9 +650,23 @@ impl Target { key!(supports_stack_protector, bool); key!(small_data_threshold_support, SmallDataThresholdSupport)?; key!(entry_name); - key!(entry_abi, Conv)?; key!(supports_xray, bool); + // we're going to run `update_from_cli`, but that won't change the target's AbiMap + // FIXME: better factor the Target definition so we enforce this on a type level + let abi_map = AbiMap::from_target(&base); + + if let Some(abi_str) = obj.remove("entry-abi") { + if let Json::String(abi_str) = abi_str { + match abi_str.parse::<ExternAbi>() { + Ok(abi) => base.options.entry_abi = abi_map.canonize_abi(abi, false).unwrap(), + Err(_) => return Err(format!("{abi_str} is not a valid ExternAbi")), + } + } else { + incorrect_type.push("entry-abi".to_owned()) + } + } + base.update_from_cli(); base.check_consistency(TargetKind::Json)?; diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index 303be54a6d7..6529c2d72c8 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -43,7 +43,7 @@ use std::str::FromStr; use std::{fmt, io}; use rustc_abi::{ - Align, Endian, ExternAbi, Integer, Size, TargetDataLayout, TargetDataLayoutErrors, + Align, CanonAbi, Endian, ExternAbi, Integer, Size, TargetDataLayout, TargetDataLayoutErrors, }; use rustc_data_structures::fx::{FxHashSet, FxIndexSet}; use rustc_fs_util::try_canonicalize; @@ -53,15 +53,16 @@ use rustc_span::{Symbol, kw, sym}; use serde_json::Value; use tracing::debug; -use crate::callconv::Conv; use crate::json::{Json, ToJson}; use crate::spec::crt_objects::CrtObjects; pub mod crt_objects; +mod abi_map; mod base; mod json; +pub use abi_map::AbiMap; pub use base::apple; pub use base::avr::ef_avr_arch; @@ -2655,9 +2656,9 @@ pub struct TargetOptions { /// Default value is "main" pub entry_name: StaticCow<str>, - /// The ABI of entry function. - /// Default value is `Conv::C`, i.e. C call convention - pub entry_abi: Conv, + /// The ABI of the entry function. + /// Default value is `CanonAbi::C` + pub entry_abi: CanonAbi, /// Whether the target supports XRay instrumentation. pub supports_xray: bool, @@ -2888,7 +2889,7 @@ impl Default for TargetOptions { generate_arange_section: true, supports_stack_protector: true, entry_name: "main".into(), - entry_abi: Conv::C, + entry_abi: CanonAbi::C, supports_xray: false, small_data_threshold_support: SmallDataThresholdSupport::DefaultForArch, } @@ -2914,114 +2915,9 @@ impl DerefMut for Target { } impl Target { - /// Given a function ABI, turn it into the correct ABI for this target. - pub fn adjust_abi(&self, abi: ExternAbi, c_variadic: bool) -> ExternAbi { - use ExternAbi::*; - match abi { - // On Windows, `extern "system"` behaves like msvc's `__stdcall`. - // `__stdcall` only applies on x86 and on non-variadic functions: - // https://learn.microsoft.com/en-us/cpp/cpp/stdcall?view=msvc-170 - System { unwind } => { - if self.is_like_windows && self.arch == "x86" && !c_variadic { - Stdcall { unwind } - } else { - C { unwind } - } - } - - EfiApi => { - if self.arch == "arm" { - Aapcs { unwind: false } - } else if self.arch == "x86_64" { - Win64 { unwind: false } - } else { - C { unwind: false } - } - } - - // See commentary in `is_abi_supported`. - Stdcall { unwind } | Thiscall { unwind } | Fastcall { unwind } => { - if self.arch == "x86" { abi } else { C { unwind } } - } - Vectorcall { unwind } => { - if ["x86", "x86_64"].contains(&&*self.arch) { - abi - } else { - C { unwind } - } - } - - // The Windows x64 calling convention we use for `extern "Rust"` - // <https://learn.microsoft.com/en-us/cpp/build/x64-software-conventions#register-volatility-and-preservation> - // expects the callee to save `xmm6` through `xmm15`, but `PreserveMost` - // (that we use by default for `extern "rust-cold"`) doesn't save any of those. - // So to avoid bloating callers, just use the Rust convention here. - RustCold if self.is_like_windows && self.arch == "x86_64" => Rust, - - abi => abi, - } - } - pub fn is_abi_supported(&self, abi: ExternAbi) -> bool { - use ExternAbi::*; - match abi { - Rust | C { .. } | System { .. } | RustCall | Unadjusted | Cdecl { .. } | RustCold => { - true - } - EfiApi => { - ["arm", "aarch64", "riscv32", "riscv64", "x86", "x86_64"].contains(&&self.arch[..]) - } - X86Interrupt => ["x86", "x86_64"].contains(&&self.arch[..]), - Aapcs { .. } => "arm" == self.arch, - CCmseNonSecureCall | CCmseNonSecureEntry => { - ["thumbv8m.main-none-eabi", "thumbv8m.main-none-eabihf", "thumbv8m.base-none-eabi"] - .contains(&&self.llvm_target[..]) - } - Win64 { .. } | SysV64 { .. } => self.arch == "x86_64", - PtxKernel => self.arch == "nvptx64", - GpuKernel => ["amdgpu", "nvptx64"].contains(&&self.arch[..]), - Msp430Interrupt => self.arch == "msp430", - RiscvInterruptM | RiscvInterruptS => ["riscv32", "riscv64"].contains(&&self.arch[..]), - AvrInterrupt | AvrNonBlockingInterrupt => self.arch == "avr", - Thiscall { .. } => self.arch == "x86", - // On windows these fall-back to platform native calling convention (C) when the - // architecture is not supported. - // - // This is I believe a historical accident that has occurred as part of Microsoft - // striving to allow most of the code to "just" compile when support for 64-bit x86 - // was added and then later again, when support for ARM architectures was added. - // - // This is well documented across MSDN. Support for this in Rust has been added in - // #54576. This makes much more sense in context of Microsoft's C++ than it does in - // Rust, but there isn't much leeway remaining here to change it back at the time this - // comment has been written. - // - // Following are the relevant excerpts from the MSDN documentation. - // - // > The __vectorcall calling convention is only supported in native code on x86 and - // x64 processors that include Streaming SIMD Extensions 2 (SSE2) and above. - // > ... - // > On ARM machines, __vectorcall is accepted and ignored by the compiler. - // - // -- https://docs.microsoft.com/en-us/cpp/cpp/vectorcall?view=msvc-160 - // - // > On ARM and x64 processors, __stdcall is accepted and ignored by the compiler; - // - // -- https://docs.microsoft.com/en-us/cpp/cpp/stdcall?view=msvc-160 - // - // > In most cases, keywords or compiler switches that specify an unsupported - // > convention on a particular platform are ignored, and the platform default - // > convention is used. - // - // -- https://docs.microsoft.com/en-us/cpp/cpp/argument-passing-and-naming-conventions - Stdcall { .. } | Fastcall { .. } | Vectorcall { .. } if self.is_like_windows => true, - // Outside of Windows we want to only support these calling conventions for the - // architectures for which these calling conventions are actually well defined. - Stdcall { .. } | Fastcall { .. } if self.arch == "x86" => true, - Vectorcall { .. } if ["x86", "x86_64"].contains(&&self.arch[..]) => true, - // Reject these calling conventions everywhere else. - Stdcall { .. } | Fastcall { .. } | Vectorcall { .. } => false, - } + let abi_map = AbiMap::from_target(self); + abi_map.canonize_abi(abi, false).is_mapped() } /// Minimum integer size in bits that this target can perform atomic diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unknown_uefi.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_uefi.rs index 07f853dacaf..0cf6a879462 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_unknown_uefi.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_uefi.rs @@ -5,7 +5,8 @@ // The win64 ABI is used. It differs from the sysv64 ABI, so we must use a windows target with // LLVM. "x86_64-unknown-windows" is used to get the minimal subset of windows-specific features. -use crate::callconv::Conv; +use rustc_abi::{CanonAbi, X86Call}; + use crate::spec::{RustcAbi, Target, TargetMetadata, base}; pub(crate) fn target() -> Target { @@ -13,7 +14,7 @@ pub(crate) fn target() -> Target { base.cpu = "x86-64".into(); base.plt_by_default = false; base.max_atomic_width = Some(64); - base.entry_abi = Conv::X86_64Win64; + base.entry_abi = CanonAbi::X86(X86Call::Win64); // We disable MMX and SSE for now, even though UEFI allows using them. Problem is, you have to // enable these CPU features explicitly before their first use, otherwise their instructions diff --git a/compiler/rustc_trait_selection/messages.ftl b/compiler/rustc_trait_selection/messages.ftl index 9b949a0a795..8232da4df43 100644 --- a/compiler/rustc_trait_selection/messages.ftl +++ b/compiler/rustc_trait_selection/messages.ftl @@ -72,8 +72,6 @@ trait_selection_adjust_signature_remove_borrow = consider adjusting the signatur trait_selection_ascribe_user_type_prove_predicate = ...so that the where clause holds -trait_selection_async_closure_not_fn = async closure does not implement `{$kind}` because it captures state from its environment - trait_selection_await_both_futures = consider `await`ing on both `Future`s trait_selection_await_future = consider `await`ing on the `Future` trait_selection_await_note = calling an async function returns a future @@ -123,6 +121,8 @@ trait_selection_closure_kind_requirement = the requirement to implement `{$trait trait_selection_compare_impl_item_obligation = ...so that the definition in impl matches the definition from the trait trait_selection_consider_specifying_length = consider specifying the actual array length +trait_selection_coro_closure_not_fn = {$coro_kind}closure does not implement `{$kind}` because it captures state from its environment + trait_selection_data_flows = ...but data{$label_var1_exists -> [true] {" "}from `{$label_var1}` *[false] {""} diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs index 9b5e421e0e4..fc5be111144 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs @@ -42,9 +42,7 @@ use super::{ use crate::error_reporting::TypeErrCtxt; use crate::error_reporting::infer::TyCategory; use crate::error_reporting::traits::report_dyn_incompatibility; -use crate::errors::{ - AsyncClosureNotFn, ClosureFnMutLabel, ClosureFnOnceLabel, ClosureKindMismatch, -}; +use crate::errors::{ClosureFnMutLabel, ClosureFnOnceLabel, ClosureKindMismatch, CoroClosureNotFn}; use crate::infer::{self, InferCtxt, InferCtxtExt as _}; use crate::traits::query::evaluate_obligation::InferCtxtExt as _; use crate::traits::{ @@ -886,9 +884,18 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { // is unimplemented is because async closures don't implement `Fn`/`FnMut` // if they have captures. if has_self_borrows && expected_kind != ty::ClosureKind::FnOnce { - let mut err = self.dcx().create_err(AsyncClosureNotFn { + let coro_kind = match self + .tcx + .coroutine_kind(self.tcx.coroutine_for_closure(closure_def_id)) + .unwrap() + { + rustc_hir::CoroutineKind::Desugared(desugaring, _) => desugaring.to_string(), + coro => coro.to_string(), + }; + let mut err = self.dcx().create_err(CoroClosureNotFn { span: self.tcx.def_span(closure_def_id), kind: expected_kind.as_str(), + coro_kind, }); self.note_obligation_cause(&mut err, &obligation); return Some(err.emit()); diff --git a/compiler/rustc_trait_selection/src/errors.rs b/compiler/rustc_trait_selection/src/errors.rs index 779c861637a..0bea308ed5c 100644 --- a/compiler/rustc_trait_selection/src/errors.rs +++ b/compiler/rustc_trait_selection/src/errors.rs @@ -201,11 +201,12 @@ pub struct ClosureFnMutLabel { } #[derive(Diagnostic)] -#[diag(trait_selection_async_closure_not_fn)] -pub(crate) struct AsyncClosureNotFn { +#[diag(trait_selection_coro_closure_not_fn)] +pub(crate) struct CoroClosureNotFn { #[primary_span] pub span: Span, pub kind: &'static str, + pub coro_kind: String, } #[derive(Diagnostic)] diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs index 7d869b27445..97ecf9702e6 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -11,7 +11,7 @@ use std::ops::ControlFlow; use hir::LangItem; use hir::def_id::DefId; use rustc_data_structures::fx::{FxHashSet, FxIndexSet}; -use rustc_hir as hir; +use rustc_hir::{self as hir, CoroutineDesugaring, CoroutineKind}; use rustc_infer::traits::{Obligation, PolyTraitObligation, SelectionError}; use rustc_middle::ty::fast_reject::DeepRejectCtxt; use rustc_middle::ty::{self, Ty, TypeVisitableExt, TypingMode, elaborate}; @@ -438,6 +438,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } } + #[instrument(level = "debug", skip(self, candidates))] fn assemble_async_closure_candidates( &mut self, obligation: &PolyTraitObligation<'tcx>, @@ -446,15 +447,30 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let goal_kind = self.tcx().async_fn_trait_kind_from_def_id(obligation.predicate.def_id()).unwrap(); + debug!("self_ty = {:?}", obligation.self_ty().skip_binder().kind()); match *obligation.self_ty().skip_binder().kind() { - ty::CoroutineClosure(_, args) => { + ty::CoroutineClosure(def_id, args) => { if let Some(closure_kind) = args.as_coroutine_closure().kind_ty().to_opt_closure_kind() && !closure_kind.extends(goal_kind) { return; } - candidates.vec.push(AsyncClosureCandidate); + + // Make sure this is actually an async closure. + let Some(coroutine_kind) = + self.tcx().coroutine_kind(self.tcx().coroutine_for_closure(def_id)) + else { + bug!("coroutine with no kind"); + }; + + debug!(?coroutine_kind); + match coroutine_kind { + CoroutineKind::Desugared(CoroutineDesugaring::Async, _) => { + candidates.vec.push(AsyncClosureCandidate); + } + _ => (), + } } // Closures and fn pointers implement `AsyncFn*` if their return types // implement `Future`, which is checked later. diff --git a/compiler/rustc_ty_utils/src/abi.rs b/compiler/rustc_ty_utils/src/abi.rs index 2b49d7ac8b5..83d7416b03e 100644 --- a/compiler/rustc_ty_utils/src/abi.rs +++ b/compiler/rustc_ty_utils/src/abi.rs @@ -13,7 +13,7 @@ use rustc_middle::ty::{self, InstanceKind, Ty, TyCtxt}; use rustc_session::config::OptLevel; use rustc_span::def_id::DefId; use rustc_target::callconv::{ - ArgAbi, ArgAttribute, ArgAttributes, ArgExtension, Conv, FnAbi, PassMode, RiscvInterruptKind, + AbiMap, ArgAbi, ArgAttribute, ArgAttributes, ArgExtension, FnAbi, PassMode, }; use tracing::debug; @@ -240,45 +240,6 @@ fn fn_sig_for_fn_abi<'tcx>( } } -#[inline] -fn conv_from_spec_abi(tcx: TyCtxt<'_>, abi: ExternAbi, c_variadic: bool) -> Conv { - use rustc_abi::ExternAbi::*; - match tcx.sess.target.adjust_abi(abi, c_variadic) { - Rust | RustCall => Conv::Rust, - - // This is intentionally not using `Conv::Cold`, as that has to preserve - // even SIMD registers, which is generally not a good trade-off. - RustCold => Conv::PreserveMost, - - // It's the ABI's job to select this, not ours. - System { .. } => bug!("system abi should be selected elsewhere"), - EfiApi => bug!("eficall abi should be selected elsewhere"), - - Stdcall { .. } => Conv::X86Stdcall, - Fastcall { .. } => Conv::X86Fastcall, - Vectorcall { .. } => Conv::X86VectorCall, - Thiscall { .. } => Conv::X86ThisCall, - C { .. } => Conv::C, - Unadjusted => Conv::C, - Win64 { .. } => Conv::X86_64Win64, - SysV64 { .. } => Conv::X86_64SysV, - Aapcs { .. } => Conv::ArmAapcs, - CCmseNonSecureCall => Conv::CCmseNonSecureCall, - CCmseNonSecureEntry => Conv::CCmseNonSecureEntry, - PtxKernel => Conv::GpuKernel, - Msp430Interrupt => Conv::Msp430Intr, - X86Interrupt => Conv::X86Intr, - GpuKernel => Conv::GpuKernel, - AvrInterrupt => Conv::AvrInterrupt, - AvrNonBlockingInterrupt => Conv::AvrNonBlockingInterrupt, - RiscvInterruptM => Conv::RiscvInterrupt { kind: RiscvInterruptKind::Machine }, - RiscvInterruptS => Conv::RiscvInterrupt { kind: RiscvInterruptKind::Supervisor }, - - // These API constants ought to be more specific... - Cdecl { .. } => Conv::C, - } -} - fn fn_abi_of_fn_ptr<'tcx>( tcx: TyCtxt<'tcx>, query: ty::PseudoCanonicalInput<'tcx, (ty::PolyFnSig<'tcx>, &'tcx ty::List<Ty<'tcx>>)>, @@ -529,7 +490,8 @@ fn fn_abi_new_uncached<'tcx>( }; let sig = tcx.normalize_erasing_regions(cx.typing_env, sig); - let conv = conv_from_spec_abi(cx.tcx(), sig.abi, sig.c_variadic); + let abi_map = AbiMap::from_target(&tcx.sess.target); + let conv = abi_map.canonize_abi(sig.abi, sig.c_variadic).unwrap(); let mut inputs = sig.inputs(); let extra_args = if sig.abi == ExternAbi::RustCall { |
