Auto merge of #117919 - daxpedda:wasm-c-abi, r=wesleywiser
Introduce perma-unstable `wasm-c-abi` flag Now that `wasm-bindgen` v0.2.88 supports the spec-compliant C ABI, the idea is to switch to that in a future version of Rust. In the meantime it would be good to let people test and play around with it. This PR introduces a new perma-unstable `-Zwasm-c-abi` compiler flag, which switches to the new spec-compliant C ABI when targeting `wasm32-unknown-unknown`. Alternatively, we could also stabilize this and then deprecate it when we switch. I will leave this to the Rust maintainers to decide. This is a companion PR to #117918, but they could be merged independently. MCP: https://github.com/rust-lang/compiler-team/issues/703 Tracking issue: https://github.com/rust-lang/rust/issues/122532
This commit is contained in:
commit
13e63f7490
11 changed files with 95 additions and 44 deletions
|
@ -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;
|
||||
|
@ -829,7 +829,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() {
|
||||
|
@ -886,7 +886,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)
|
||||
|
@ -895,7 +897,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)
|
||||
|
|
|
@ -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};
|
||||
|
@ -1915,6 +1915,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<T> = Cow<'static, T>;
|
||||
|
||||
/// Optional aspects of a target specification.
|
||||
|
@ -2273,9 +2286,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<Abi>,
|
||||
|
||||
/// Minimum number of bits in #[repr(C)] enum. Defaults to the size of c_int
|
||||
pub c_enum_min_bits: Option<u64>,
|
||||
|
||||
|
@ -2507,7 +2517,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,
|
||||
|
@ -2538,9 +2547,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<C>(&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::Legacy
|
||||
{
|
||||
Abi::Wasm
|
||||
} else {
|
||||
abi
|
||||
}
|
||||
}
|
||||
|
||||
// On Windows, `extern "system"` behaves like msvc's `__stdcall`.
|
||||
// `__stdcall` only applies on x86 and on non-variadic functions:
|
||||
|
@ -3079,16 +3100,6 @@ impl Target {
|
|||
}
|
||||
}
|
||||
} );
|
||||
($key_name:ident, Option<Abi>) => ( {
|
||||
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() {
|
||||
|
@ -3238,7 +3249,6 @@ impl Target {
|
|||
key!(split_debuginfo, SplitDebuginfo)?;
|
||||
key!(supported_split_debuginfo, fallible_list)?;
|
||||
key!(supported_sanitizers, SanitizerSet)?;
|
||||
key!(default_adjusted_cabi, Option<Abi>)?;
|
||||
key!(generate_arange_section, bool);
|
||||
key!(supports_stack_protector, bool);
|
||||
key!(entry_name);
|
||||
|
@ -3502,10 +3512,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());
|
||||
|
|
|
@ -10,23 +10,12 @@
|
|||
//! This target is more or less managed by the Rust and WebAssembly Working
|
||||
//! Group nowadays at <https://github.com/rustwasm>.
|
||||
|
||||
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),
|
||||
&[
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue