From f09c19ac3a514a0f74e25443f48898f80bde561c Mon Sep 17 00:00:00 2001 From: daxpedda Date: Tue, 27 Feb 2024 23:06:44 +0100 Subject: [PATCH 1/2] Introduce perma-unstable `wasm-c-abi` flag --- compiler/rustc_codegen_gcc/src/builder.rs | 8 ++++- compiler/rustc_codegen_gcc/src/context.rs | 8 ++++- compiler/rustc_interface/src/tests.rs | 5 +++- compiler/rustc_middle/src/ty/layout.rs | 16 +++++++++- compiler/rustc_session/src/config.rs | 3 +- compiler/rustc_session/src/options.rs | 16 +++++++++- compiler/rustc_target/src/abi/call/mod.rs | 10 ++++--- compiler/rustc_target/src/spec/mod.rs | 29 +++++++++++++++++-- compiler/rustc_ty_utils/src/abi.rs | 2 +- .../src/compiler-flags/wasm-c-abi.md | 10 +++++++ 10 files changed, 94 insertions(+), 13 deletions(-) create mode 100644 src/doc/unstable-book/src/compiler-flags/wasm-c-abi.md diff --git a/compiler/rustc_codegen_gcc/src/builder.rs b/compiler/rustc_codegen_gcc/src/builder.rs index f5cda81f6ab86..3cfc308c54638 100644 --- a/compiler/rustc_codegen_gcc/src/builder.rs +++ b/compiler/rustc_codegen_gcc/src/builder.rs @@ -31,7 +31,7 @@ use rustc_span::Span; use rustc_target::abi::{ self, call::FnAbi, Align, HasDataLayout, Size, TargetDataLayout, WrappingRange, }; -use rustc_target::spec::{HasTargetSpec, Target}; +use rustc_target::spec::{HasTargetSpec, HasWasmCAbiOpt, Target, WasmCAbi}; use crate::common::{type_is_pointer, SignType, TypeReflection}; use crate::context::CodegenCx; @@ -2349,6 +2349,12 @@ impl<'tcx> HasTargetSpec for Builder<'_, '_, 'tcx> { } } +impl<'tcx> HasWasmCAbiOpt for Builder<'_, '_, 'tcx> { + fn wasm_c_abi_opt(&self) -> WasmCAbi { + self.cx.wasm_c_abi_opt() + } +} + pub trait ToGccComp { fn to_gcc_comparison(&self) -> ComparisonOp; } diff --git a/compiler/rustc_codegen_gcc/src/context.rs b/compiler/rustc_codegen_gcc/src/context.rs index bc3d62f2679d9..99c079f40e03b 100644 --- a/compiler/rustc_codegen_gcc/src/context.rs +++ b/compiler/rustc_codegen_gcc/src/context.rs @@ -20,7 +20,7 @@ use rustc_span::{source_map::respan, Span}; use rustc_target::abi::{ call::FnAbi, HasDataLayout, PointeeInfo, Size, TargetDataLayout, VariantIdx, }; -use rustc_target::spec::{HasTargetSpec, Target, TlsModel}; +use rustc_target::spec::{HasTargetSpec, HasWasmCAbiOpt, Target, TlsModel, WasmCAbi}; use crate::callee::get_fn; use crate::common::SignType; @@ -555,6 +555,12 @@ impl<'gcc, 'tcx> HasTargetSpec for CodegenCx<'gcc, 'tcx> { } } +impl<'gcc, 'tcx> HasWasmCAbiOpt for CodegenCx<'gcc, 'tcx> { + fn wasm_c_abi_opt(&self) -> WasmCAbi { + self.tcx.sess.opts.unstable_opts.wasm_c_abi + } +} + impl<'gcc, 'tcx> LayoutOfHelpers<'tcx> for CodegenCx<'gcc, 'tcx> { type LayoutOfResult = TyAndLayout<'tcx>; diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index 4f15d1c1d3a0b..758118cb38beb 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -17,7 +17,9 @@ use rustc_session::{build_session, getopts, CompilerIO, EarlyDiagCtxt, Session}; use rustc_span::edition::{Edition, DEFAULT_EDITION}; use rustc_span::symbol::sym; use rustc_span::{FileName, SourceFileHashAlgorithm}; -use rustc_target::spec::{CodeModel, LinkerFlavorCli, MergeFunctions, PanicStrategy, RelocModel}; +use rustc_target::spec::{ + CodeModel, LinkerFlavorCli, MergeFunctions, PanicStrategy, RelocModel, WasmCAbi, +}; use rustc_target::spec::{RelroLevel, SanitizerSet, SplitDebuginfo, StackProtector, TlsModel}; use std::collections::{BTreeMap, BTreeSet}; use std::num::NonZero; @@ -836,6 +838,7 @@ fn test_unstable_options_tracking_hash() { tracked!(verify_llvm_ir, true); tracked!(virtual_function_elimination, true); tracked!(wasi_exec_model, Some(WasiExecModel::Reactor)); + tracked!(wasm_c_abi, WasmCAbi::Spec); // tidy-alphabetical-end macro_rules! tracked_no_crate_hash { diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index b1bfd2f1105a8..e7ef7e381c2f8 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -15,7 +15,9 @@ use rustc_span::symbol::{sym, Symbol}; use rustc_span::{ErrorGuaranteed, Span, DUMMY_SP}; use rustc_target::abi::call::FnAbi; use rustc_target::abi::*; -use rustc_target::spec::{abi::Abi as SpecAbi, HasTargetSpec, PanicStrategy, Target}; +use rustc_target::spec::{ + abi::Abi as SpecAbi, HasTargetSpec, HasWasmCAbiOpt, PanicStrategy, Target, WasmCAbi, +}; use std::borrow::Cow; use std::cmp; @@ -539,6 +541,12 @@ impl<'tcx> HasTargetSpec for TyCtxt<'tcx> { } } +impl<'tcx> HasWasmCAbiOpt for TyCtxt<'tcx> { + fn wasm_c_abi_opt(&self) -> WasmCAbi { + self.sess.opts.unstable_opts.wasm_c_abi + } +} + impl<'tcx> HasTyCtxt<'tcx> for TyCtxt<'tcx> { #[inline] fn tcx(&self) -> TyCtxt<'tcx> { @@ -584,6 +592,12 @@ impl<'tcx, T: HasTargetSpec> HasTargetSpec for LayoutCx<'tcx, T> { } } +impl<'tcx, T: HasWasmCAbiOpt> HasWasmCAbiOpt for LayoutCx<'tcx, T> { + fn wasm_c_abi_opt(&self) -> WasmCAbi { + self.tcx.wasm_c_abi_opt() + } +} + impl<'tcx, T: HasTyCtxt<'tcx>> HasTyCtxt<'tcx> for LayoutCx<'tcx, T> { fn tcx(&self) -> TyCtxt<'tcx> { self.tcx.tcx() diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index 61a220428b03b..2213a626d4fef 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -3227,7 +3227,7 @@ pub(crate) mod dep_tracking { use rustc_feature::UnstableFeatures; use rustc_span::edition::Edition; use rustc_span::RealFileName; - use rustc_target::spec::{CodeModel, MergeFunctions, PanicStrategy, RelocModel}; + use rustc_target::spec::{CodeModel, MergeFunctions, PanicStrategy, RelocModel, WasmCAbi}; use rustc_target::spec::{ RelroLevel, SanitizerSet, SplitDebuginfo, StackProtector, TargetTriple, TlsModel, }; @@ -3324,6 +3324,7 @@ pub(crate) mod dep_tracking { Polonius, InliningThreshold, FunctionReturn, + WasmCAbi, ); impl DepTrackingHash for (T1, T2) diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index 93bef82e4ba15..75f3130a8bd57 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -8,7 +8,9 @@ use rustc_data_structures::profiling::TimePassesFormat; use rustc_data_structures::stable_hasher::Hash64; use rustc_errors::ColorConfig; use rustc_errors::{LanguageIdentifier, TerminalUrl}; -use rustc_target::spec::{CodeModel, LinkerFlavorCli, MergeFunctions, PanicStrategy, SanitizerSet}; +use rustc_target::spec::{ + CodeModel, LinkerFlavorCli, MergeFunctions, PanicStrategy, SanitizerSet, WasmCAbi, +}; use rustc_target::spec::{ RelocModel, RelroLevel, SplitDebuginfo, StackProtector, TargetTriple, TlsModel, }; @@ -437,6 +439,7 @@ mod desc { "either a boolean (`yes`, `no`, `on`, `off`, etc), or a non-negative number"; pub const parse_llvm_module_flag: &str = ":::. Type must currently be `u32`. Behavior should be one of (`error`, `warning`, `require`, `override`, `append`, `appendunique`, `max`, `min`)"; pub const parse_function_return: &str = "`keep` or `thunk-extern`"; + pub const parse_wasm_c_abi: &str = "`legacy` or `spec`"; } mod parse { @@ -1402,6 +1405,15 @@ mod parse { } true } + + pub(crate) fn parse_wasm_c_abi(slot: &mut WasmCAbi, v: Option<&str>) -> bool { + match v { + Some("spec") => *slot = WasmCAbi::Spec, + Some("legacy") => *slot = WasmCAbi::Legacy, + _ => return false, + } + true + } } options! { @@ -2021,6 +2033,8 @@ written to standard error output)"), Requires `-Clto[=[fat,yes]]`"), wasi_exec_model: Option = (None, parse_wasi_exec_model, [TRACKED], "whether to build a wasi command or reactor"), + wasm_c_abi: WasmCAbi = (WasmCAbi::Legacy, parse_wasm_c_abi, [TRACKED], + "use spec-compliant C ABI for `wasm32-unknown-unknown` (default: legacy)"), write_long_types_to_disk: bool = (true, parse_bool, [UNTRACKED], "whether long type names should be written to files instead of being printed in errors"), // tidy-alphabetical-end diff --git a/compiler/rustc_target/src/abi/call/mod.rs b/compiler/rustc_target/src/abi/call/mod.rs index f4967b94e930a..930edfe1f0df3 100644 --- a/compiler/rustc_target/src/abi/call/mod.rs +++ b/compiler/rustc_target/src/abi/call/mod.rs @@ -1,6 +1,6 @@ use crate::abi::{self, Abi, Align, FieldsShape, Size}; use crate::abi::{HasDataLayout, TyAbiInterface, TyAndLayout}; -use crate::spec::{self, HasTargetSpec}; +use crate::spec::{self, HasTargetSpec, HasWasmCAbiOpt}; use rustc_span::Symbol; use std::fmt; use std::str::FromStr; @@ -782,7 +782,7 @@ impl<'a, Ty> FnAbi<'a, Ty> { ) -> Result<(), AdjustForForeignAbiError> where Ty: TyAbiInterface<'a, C> + Copy, - C: HasDataLayout + HasTargetSpec, + C: HasDataLayout + HasTargetSpec + HasWasmCAbiOpt, { if abi == spec::abi::Abi::X86Interrupt { if let Some(arg) = self.args.first_mut() { @@ -839,7 +839,9 @@ impl<'a, Ty> FnAbi<'a, Ty> { "sparc" => sparc::compute_abi_info(cx, self), "sparc64" => sparc64::compute_abi_info(cx, self), "nvptx64" => { - if cx.target_spec().adjust_abi(abi, self.c_variadic) == spec::abi::Abi::PtxKernel { + if cx.target_spec().adjust_abi(cx, abi, self.c_variadic) + == spec::abi::Abi::PtxKernel + { nvptx64::compute_ptx_kernel_abi_info(cx, self) } else { nvptx64::compute_abi_info(self) @@ -848,7 +850,7 @@ impl<'a, Ty> FnAbi<'a, Ty> { "hexagon" => hexagon::compute_abi_info(self), "riscv32" | "riscv64" => riscv::compute_abi_info(cx, self), "wasm32" | "wasm64" => { - if cx.target_spec().adjust_abi(abi, self.c_variadic) == spec::abi::Abi::Wasm { + if cx.target_spec().adjust_abi(cx, abi, self.c_variadic) == spec::abi::Abi::Wasm { wasm::compute_wasm_abi_info(self) } else { wasm::compute_c_abi_info(cx, self) diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index 3b6e15fad4661..c42e818167c3b 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -1807,6 +1807,19 @@ impl HasTargetSpec for Target { } } +/// Which C ABI to use for `wasm32-unknown-unknown`. +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub enum WasmCAbi { + /// Spec-compliant C ABI. + Spec, + /// Legacy ABI. Which is non-spec-compliant. + Legacy, +} + +pub trait HasWasmCAbiOpt { + fn wasm_c_abi_opt(&self) -> WasmCAbi; +} + type StaticCow = Cow<'static, T>; /// Optional aspects of a target specification. @@ -2417,9 +2430,21 @@ 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: Abi, c_variadic: bool) -> Abi { + pub fn adjust_abi(&self, cx: &C, abi: Abi, c_variadic: bool) -> Abi + where + C: HasWasmCAbiOpt, + { match abi { - Abi::C { .. } => self.default_adjusted_cabi.unwrap_or(abi), + Abi::C { .. } => { + if self.arch == "wasm32" + && self.os == "unknown" + && cx.wasm_c_abi_opt() == WasmCAbi::Spec + { + abi + } else { + self.default_adjusted_cabi.unwrap_or(abi) + } + } // On Windows, `extern "system"` behaves like msvc's `__stdcall`. // `__stdcall` only applies on x86 and on non-variadic functions: diff --git a/compiler/rustc_ty_utils/src/abi.rs b/compiler/rustc_ty_utils/src/abi.rs index a5328baadb5fc..71bcf898ceab2 100644 --- a/compiler/rustc_ty_utils/src/abi.rs +++ b/compiler/rustc_ty_utils/src/abi.rs @@ -311,7 +311,7 @@ fn fn_sig_for_fn_abi<'tcx>( #[inline] fn conv_from_spec_abi(tcx: TyCtxt<'_>, abi: SpecAbi, c_variadic: bool) -> Conv { use rustc_target::spec::abi::Abi::*; - match tcx.sess.target.adjust_abi(abi, c_variadic) { + match tcx.sess.target.adjust_abi(&tcx, abi, c_variadic) { RustIntrinsic | Rust | RustCall => Conv::Rust, // This is intentionally not using `Conv::Cold`, as that has to preserve diff --git a/src/doc/unstable-book/src/compiler-flags/wasm-c-abi.md b/src/doc/unstable-book/src/compiler-flags/wasm-c-abi.md new file mode 100644 index 0000000000000..138a98dbe3dcd --- /dev/null +++ b/src/doc/unstable-book/src/compiler-flags/wasm-c-abi.md @@ -0,0 +1,10 @@ +# `wasm-c-abi` + +This option controls whether Rust uses the spec-compliant C ABI when compiling +for the `wasm32-unknown-unknown` target. + +This makes it possible to be ABI-compatible with all other spec-compliant Wasm +like Rusts `wasm32-wasi`. + +This compiler flag is perma-unstable, as it will be enabled by default in the +future with no option to fall back to the old non-spec-compliant ABI. From 9e2c65893dcf5e8da2fc7cd25af94ba3233e9c51 Mon Sep 17 00:00:00 2001 From: daxpedda Date: Wed, 13 Dec 2023 19:36:17 +0100 Subject: [PATCH 2/2] Remove `TargetOptions::default_adjusted_cabi` Co-Authored-By: Ralf Jung <330628+RalfJung@users.noreply.github.com> --- compiler/rustc_target/src/spec/mod.rs | 27 +++---------------- .../spec/targets/wasm32_unknown_unknown.rs | 11 -------- 2 files changed, 4 insertions(+), 34 deletions(-) diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index c42e818167c3b..578faf3f93534 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -37,7 +37,7 @@ use crate::abi::call::Conv; use crate::abi::{Endian, Integer, Size, TargetDataLayout, TargetDataLayoutErrors}; use crate::json::{Json, ToJson}; -use crate::spec::abi::{lookup as lookup_abi, Abi}; +use crate::spec::abi::Abi; use crate::spec::crt_objects::CrtObjects; use rustc_fs_util::try_canonicalize; use rustc_serialize::{Decodable, Decoder, Encodable, Encoder}; @@ -2167,9 +2167,6 @@ pub struct TargetOptions { /// distributed with the target, the sanitizer should still appear in this list for the target. pub supported_sanitizers: SanitizerSet, - /// If present it's a default value to use for adjusting the C ABI. - pub default_adjusted_cabi: Option, - /// Minimum number of bits in #[repr(C)] enum. Defaults to the size of c_int pub c_enum_min_bits: Option, @@ -2399,7 +2396,6 @@ impl Default for TargetOptions { // `Off` is supported by default, but targets can remove this manually, e.g. Windows. supported_split_debuginfo: Cow::Borrowed(&[SplitDebuginfo::Off]), supported_sanitizers: SanitizerSet::empty(), - default_adjusted_cabi: None, c_enum_min_bits: None, generate_arange_section: true, supports_stack_protector: true, @@ -2438,11 +2434,11 @@ impl Target { Abi::C { .. } => { if self.arch == "wasm32" && self.os == "unknown" - && cx.wasm_c_abi_opt() == WasmCAbi::Spec + && cx.wasm_c_abi_opt() == WasmCAbi::Legacy { - abi + Abi::Wasm } else { - self.default_adjusted_cabi.unwrap_or(abi) + abi } } @@ -2967,16 +2963,6 @@ impl Target { } } } ); - ($key_name:ident, Option) => ( { - let name = (stringify!($key_name)).replace("_", "-"); - obj.remove(&name).and_then(|o| o.as_str().and_then(|s| { - match lookup_abi(s) { - Ok(abi) => base.$key_name = Some(abi), - _ => return Some(Err(format!("'{}' is not a valid value for abi", s))), - } - Some(Ok(())) - })).unwrap_or(Ok(())) - } ); ($key_name:ident, TargetFamilies) => ( { if let Some(value) = obj.remove("target-family") { if let Some(v) = value.as_array() { @@ -3126,7 +3112,6 @@ impl Target { key!(split_debuginfo, SplitDebuginfo)?; key!(supported_split_debuginfo, fallible_list)?; key!(supported_sanitizers, SanitizerSet)?; - key!(default_adjusted_cabi, Option)?; key!(generate_arange_section, bool); key!(supports_stack_protector, bool); key!(entry_name); @@ -3390,10 +3375,6 @@ impl ToJson for Target { target_option_val!(entry_abi); target_option_val!(supports_xray); - if let Some(abi) = self.default_adjusted_cabi { - d.insert("default-adjusted-cabi".into(), Abi::name(abi).to_json()); - } - // Serializing `-Clink-self-contained` needs a dynamic key to support the // backwards-compatible variants. d.insert(self.link_self_contained.json_key().into(), self.link_self_contained.to_json()); diff --git a/compiler/rustc_target/src/spec/targets/wasm32_unknown_unknown.rs b/compiler/rustc_target/src/spec/targets/wasm32_unknown_unknown.rs index 94ded57d2f0cd..7db4d8aca5628 100644 --- a/compiler/rustc_target/src/spec/targets/wasm32_unknown_unknown.rs +++ b/compiler/rustc_target/src/spec/targets/wasm32_unknown_unknown.rs @@ -10,23 +10,12 @@ //! This target is more or less managed by the Rust and WebAssembly Working //! Group nowadays at . -use crate::spec::abi::Abi; use crate::spec::{base, Cc, LinkerFlavor, Target}; pub fn target() -> Target { let mut options = base::wasm::options(); options.os = "unknown".into(); - // This is a default for backwards-compatibility with the original - // definition of this target oh-so-long-ago. Once the "wasm" ABI is - // stable and the wasm-bindgen project has switched to using it then there's - // no need for this and it can be removed. - // - // Currently this is the reason that this target's ABI is mismatched with - // clang's ABI. This means that, in the limit, you can't merge C and Rust - // code on this target due to this ABI mismatch. - options.default_adjusted_cabi = Some(Abi::Wasm); - options.add_pre_link_args( LinkerFlavor::WasmLld(Cc::No), &[