diff options
Diffstat (limited to 'compiler')
| -rw-r--r-- | compiler/rustc_ast_passes/src/feature_gate.rs | 8 | ||||
| -rw-r--r-- | compiler/rustc_codegen_llvm/src/attributes.rs | 44 | ||||
| -rw-r--r-- | compiler/rustc_feature/src/active.rs | 3 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/ty/layout.rs | 2 | ||||
| -rw-r--r-- | compiler/rustc_mir_build/src/build/mod.rs | 1 | ||||
| -rw-r--r-- | compiler/rustc_span/src/symbol.rs | 1 | ||||
| -rw-r--r-- | compiler/rustc_target/src/abi/call/mod.rs | 18 | ||||
| -rw-r--r-- | compiler/rustc_target/src/abi/call/wasm.rs (renamed from compiler/rustc_target/src/abi/call/wasm32.rs) | 27 | ||||
| -rw-r--r-- | compiler/rustc_target/src/abi/call/wasm32_bindgen_compat.rs | 29 | ||||
| -rw-r--r-- | compiler/rustc_target/src/abi/call/wasm64.rs | 58 | ||||
| -rw-r--r-- | compiler/rustc_target/src/spec/abi.rs | 15 | ||||
| -rw-r--r-- | compiler/rustc_target/src/spec/mod.rs | 22 | ||||
| -rw-r--r-- | compiler/rustc_target/src/spec/wasm32_unknown_unknown.rs | 12 |
13 files changed, 121 insertions, 119 deletions
diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs index 3724438cc6e..87c4bfae1af 100644 --- a/compiler/rustc_ast_passes/src/feature_gate.rs +++ b/compiler/rustc_ast_passes/src/feature_gate.rs @@ -196,6 +196,14 @@ impl<'a> PostExpansionVisitor<'a> { "thiscall-unwind ABI is experimental and subject to change" ); } + "wasm" => { + gate_feature_post!( + &self, + wasm_abi, + span, + "wasm ABI is experimental and subject to change" + ); + } abi => self .sess .parse_sess diff --git a/compiler/rustc_codegen_llvm/src/attributes.rs b/compiler/rustc_codegen_llvm/src/attributes.rs index e06c1c825f6..9e5e2b1039e 100644 --- a/compiler/rustc_codegen_llvm/src/attributes.rs +++ b/compiler/rustc_codegen_llvm/src/attributes.rs @@ -13,6 +13,7 @@ use rustc_middle::ty::query::Providers; use rustc_middle::ty::{self, TyCtxt}; use rustc_session::config::OptLevel; use rustc_session::Session; +use rustc_target::spec::abi::Abi; use rustc_target::spec::{SanitizerSet, StackProbeType}; use crate::attributes; @@ -293,7 +294,7 @@ pub fn from_fn_attrs(cx: &CodegenCx<'ll, 'tcx>, llfn: &'ll Value, instance: ty:: // The target doesn't care; the subtarget reads our attribute. apply_tune_cpu_attr(cx, llfn); - let function_features = codegen_fn_attrs + let mut function_features = codegen_fn_attrs .target_features .iter() .map(|f| { @@ -305,23 +306,10 @@ pub fn from_fn_attrs(cx: &CodegenCx<'ll, 'tcx>, llfn: &'ll Value, instance: ty:: InstructionSetAttr::ArmT32 => "+thumb-mode".to_string(), })) .collect::<Vec<String>>(); - if !function_features.is_empty() { - let mut global_features = llvm_util::llvm_global_features(cx.tcx.sess); - global_features.extend(function_features.into_iter()); - let features = global_features.join(","); - let val = CString::new(features).unwrap(); - llvm::AddFunctionAttrStringValue( - llfn, - llvm::AttributePlace::Function, - cstr!("target-features"), - &val, - ); - } - // Note that currently the `wasm-import-module` doesn't do anything, but - // eventually LLVM 7 should read this and ferry the appropriate import - // module to the output file. if cx.tcx.sess.target.is_like_wasm { + // If this function is an import from the environment but the wasm + // import has a specific module/name, apply them here. if let Some(module) = wasm_import_module(cx.tcx, instance.def_id()) { llvm::AddFunctionAttrStringValue( llfn, @@ -340,6 +328,30 @@ pub fn from_fn_attrs(cx: &CodegenCx<'ll, 'tcx>, llfn: &'ll Value, instance: ty:: &name, ); } + + // The `"wasm"` abi on wasm targets automatically enables the + // `+multivalue` feature because the purpose of the wasm abi is to match + // the WebAssembly specification, which has this feature. This won't be + // needed when LLVM enables this `multivalue` feature by default. + if !cx.tcx.is_closure(instance.def_id()) { + let abi = cx.tcx.fn_sig(instance.def_id()).abi(); + if abi == Abi::Wasm { + function_features.push("+multivalue".to_string()); + } + } + } + + if !function_features.is_empty() { + let mut global_features = llvm_util::llvm_global_features(cx.tcx.sess); + global_features.extend(function_features.into_iter()); + let features = global_features.join(","); + let val = CString::new(features).unwrap(); + llvm::AddFunctionAttrStringValue( + llfn, + llvm::AttributePlace::Function, + cstr!("target-features"), + &val, + ); } } diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs index 93de4891ec7..1a91eb600a9 100644 --- a/compiler/rustc_feature/src/active.rs +++ b/compiler/rustc_feature/src/active.rs @@ -645,6 +645,9 @@ declare_features! ( /// Allows using `#[repr(align(...))]` on function items (active, fn_align, "1.53.0", Some(82232), None), + /// Allows `extern "wasm" fn` + (active, wasm_abi, "1.53.0", Some(83788), None), + // ------------------------------------------------------------------------- // feature-group-end: actual feature gates // ------------------------------------------------------------------------- diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index e7bbdc3cceb..c2e9dba6c8e 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -2630,6 +2630,7 @@ fn fn_can_unwind( | AvrInterrupt | AvrNonBlockingInterrupt | CCmseNonSecureCall + | Wasm | RustIntrinsic | PlatformIntrinsic | Unadjusted => false, @@ -2712,6 +2713,7 @@ where AmdGpuKernel => Conv::AmdGpuKernel, AvrInterrupt => Conv::AvrInterrupt, AvrNonBlockingInterrupt => Conv::AvrNonBlockingInterrupt, + Wasm => Conv::C, // These API constants ought to be more specific... Cdecl => Conv::C, diff --git a/compiler/rustc_mir_build/src/build/mod.rs b/compiler/rustc_mir_build/src/build/mod.rs index c90f94c6d63..3a189e6b33d 100644 --- a/compiler/rustc_mir_build/src/build/mod.rs +++ b/compiler/rustc_mir_build/src/build/mod.rs @@ -609,6 +609,7 @@ fn should_abort_on_panic(tcx: TyCtxt<'_>, fn_def_id: LocalDefId, abi: Abi) -> bo | AvrInterrupt | AvrNonBlockingInterrupt | CCmseNonSecureCall + | Wasm | RustIntrinsic | PlatformIntrinsic | Unadjusted => true, diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 03fe5bcd297..ee1d206095e 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1295,6 +1295,7 @@ symbols! { vreg, vreg_low16, warn, + wasm_abi, wasm_import_module, wasm_target_feature, while_let, diff --git a/compiler/rustc_target/src/abi/call/mod.rs b/compiler/rustc_target/src/abi/call/mod.rs index 395235399ea..d9d7d467d92 100644 --- a/compiler/rustc_target/src/abi/call/mod.rs +++ b/compiler/rustc_target/src/abi/call/mod.rs @@ -18,9 +18,7 @@ mod riscv; mod s390x; mod sparc; mod sparc64; -mod wasm32; -mod wasm32_bindgen_compat; -mod wasm64; +mod wasm; mod x86; mod x86_64; mod x86_win64; @@ -648,12 +646,14 @@ impl<'a, Ty> FnAbi<'a, Ty> { "nvptx64" => nvptx64::compute_abi_info(self), "hexagon" => hexagon::compute_abi_info(self), "riscv32" | "riscv64" => riscv::compute_abi_info(cx, self), - "wasm32" => match cx.target_spec().os.as_str() { - "emscripten" | "wasi" => wasm32::compute_abi_info(cx, self), - _ => wasm32_bindgen_compat::compute_abi_info(self), - }, - "asmjs" => wasm32::compute_abi_info(cx, self), - "wasm64" => wasm64::compute_abi_info(cx, self), + "wasm32" | "wasm64" => { + if cx.target_spec().adjust_abi(abi) == spec::abi::Abi::Wasm { + wasm::compute_wasm_abi_info(self) + } else { + wasm::compute_c_abi_info(cx, self) + } + } + "asmjs" => wasm::compute_c_abi_info(cx, self), a => return Err(format!("unrecognized arch \"{}\" in target specification", a)), } diff --git a/compiler/rustc_target/src/abi/call/wasm32.rs b/compiler/rustc_target/src/abi/call/wasm.rs index ff2c0e9bb6f..bf2c08bb166 100644 --- a/compiler/rustc_target/src/abi/call/wasm32.rs +++ b/compiler/rustc_target/src/abi/call/wasm.rs @@ -40,7 +40,8 @@ where } } -pub fn compute_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>) +/// The purpose of this ABI is to match the C ABI (aka clang) exactly. +pub fn compute_c_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>) where Ty: TyAndLayoutMethods<'a, C> + Copy, C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout, @@ -56,3 +57,27 @@ where classify_arg(cx, arg); } } + +/// The purpose of this ABI is for matching the WebAssembly standard. This +/// intentionally diverges from the C ABI and is specifically crafted to take +/// advantage of LLVM's support of multiple returns in WebAssembly. +pub fn compute_wasm_abi_info<Ty>(fn_abi: &mut FnAbi<'_, Ty>) { + if !fn_abi.ret.is_ignore() { + classify_ret(&mut fn_abi.ret); + } + + for arg in &mut fn_abi.args { + if arg.is_ignore() { + continue; + } + classify_arg(arg); + } + + fn classify_ret<Ty>(ret: &mut ArgAbi<'_, Ty>) { + ret.extend_integer_width_to(32); + } + + fn classify_arg<Ty>(arg: &mut ArgAbi<'_, Ty>) { + arg.extend_integer_width_to(32); + } +} diff --git a/compiler/rustc_target/src/abi/call/wasm32_bindgen_compat.rs b/compiler/rustc_target/src/abi/call/wasm32_bindgen_compat.rs deleted file mode 100644 index 59571fd9d48..00000000000 --- a/compiler/rustc_target/src/abi/call/wasm32_bindgen_compat.rs +++ /dev/null @@ -1,29 +0,0 @@ -// This is not and has never been a correct C ABI for WebAssembly, but -// for a long time this was the C ABI that Rust used. wasm-bindgen -// depends on ABI details for this ABI and is incompatible with the -// correct C ABI, so this ABI is being kept around until wasm-bindgen -// can be fixed to work with the correct ABI. See #63649 for further -// discussion. - -use crate::abi::call::{ArgAbi, FnAbi}; - -fn classify_ret<Ty>(ret: &mut ArgAbi<'_, Ty>) { - ret.extend_integer_width_to(32); -} - -fn classify_arg<Ty>(arg: &mut ArgAbi<'_, Ty>) { - arg.extend_integer_width_to(32); -} - -pub fn compute_abi_info<Ty>(fn_abi: &mut FnAbi<'_, Ty>) { - if !fn_abi.ret.is_ignore() { - classify_ret(&mut fn_abi.ret); - } - - for arg in &mut fn_abi.args { - if arg.is_ignore() { - continue; - } - classify_arg(arg); - } -} diff --git a/compiler/rustc_target/src/abi/call/wasm64.rs b/compiler/rustc_target/src/abi/call/wasm64.rs deleted file mode 100644 index 46d670d1689..00000000000 --- a/compiler/rustc_target/src/abi/call/wasm64.rs +++ /dev/null @@ -1,58 +0,0 @@ -use crate::abi::call::{ArgAbi, FnAbi, Uniform}; -use crate::abi::{HasDataLayout, LayoutOf, TyAndLayout, TyAndLayoutMethods}; - -fn unwrap_trivial_aggregate<'a, Ty, C>(cx: &C, val: &mut ArgAbi<'a, Ty>) -> bool -where - Ty: TyAndLayoutMethods<'a, C> + Copy, - C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout, -{ - if val.layout.is_aggregate() { - if let Some(unit) = val.layout.homogeneous_aggregate(cx).ok().and_then(|ha| ha.unit()) { - let size = val.layout.size; - if unit.size == size { - val.cast_to(Uniform { unit, total: size }); - return true; - } - } - } - false -} - -fn classify_ret<'a, Ty, C>(cx: &C, ret: &mut ArgAbi<'a, Ty>) -where - Ty: TyAndLayoutMethods<'a, C> + Copy, - C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout, -{ - ret.extend_integer_width_to(64); - if ret.layout.is_aggregate() && !unwrap_trivial_aggregate(cx, ret) { - ret.make_indirect(); - } -} - -fn classify_arg<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>) -where - Ty: TyAndLayoutMethods<'a, C> + Copy, - C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout, -{ - arg.extend_integer_width_to(64); - if arg.layout.is_aggregate() && !unwrap_trivial_aggregate(cx, arg) { - arg.make_indirect_byval(); - } -} - -pub fn compute_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>) -where - Ty: TyAndLayoutMethods<'a, C> + Copy, - C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout, -{ - if !fn_abi.ret.is_ignore() { - classify_ret(cx, &mut fn_abi.ret); - } - - for arg in &mut fn_abi.args { - if arg.is_ignore() { - continue; - } - classify_arg(cx, arg); - } -} diff --git a/compiler/rustc_target/src/spec/abi.rs b/compiler/rustc_target/src/spec/abi.rs index 17eb33b8f2e..a026a623f78 100644 --- a/compiler/rustc_target/src/spec/abi.rs +++ b/compiler/rustc_target/src/spec/abi.rs @@ -34,6 +34,7 @@ pub enum Abi { AvrInterrupt, AvrNonBlockingInterrupt, CCmseNonSecureCall, + Wasm, // Multiplatform / generic ABIs System { unwind: bool }, @@ -83,6 +84,7 @@ const AbiDatas: &[AbiData] = &[ generic: false, }, AbiData { abi: Abi::CCmseNonSecureCall, name: "C-cmse-nonsecure-call", generic: false }, + AbiData { abi: Abi::Wasm, name: "wasm", generic: false }, // Cross-platform ABIs AbiData { abi: Abi::System { unwind: false }, name: "system", generic: true }, AbiData { abi: Abi::System { unwind: true }, name: "system-unwind", generic: true }, @@ -131,13 +133,14 @@ impl Abi { AvrInterrupt => 18, AvrNonBlockingInterrupt => 19, CCmseNonSecureCall => 20, + Wasm => 21, // Cross-platform ABIs - System { unwind: false } => 21, - System { unwind: true } => 22, - RustIntrinsic => 23, - RustCall => 24, - PlatformIntrinsic => 25, - Unadjusted => 26, + System { unwind: false } => 22, + System { unwind: true } => 23, + RustIntrinsic => 24, + RustCall => 25, + PlatformIntrinsic => 26, + Unadjusted => 27, }; debug_assert!( AbiDatas diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index 801cdd3ebe9..57b0a36e009 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -1254,6 +1254,9 @@ pub struct TargetOptions { /// enabled can generated on this target, but the necessary supporting libraries are not /// 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>, } impl Default for TargetOptions { @@ -1357,6 +1360,7 @@ impl Default for TargetOptions { has_thumb_interworking: false, split_debuginfo: SplitDebuginfo::Off, supported_sanitizers: SanitizerSet::empty(), + default_adjusted_cabi: None, } } } @@ -1408,6 +1412,9 @@ impl Target { Abi::C { unwind: false } } } + + Abi::C { unwind } => self.default_adjusted_cabi.unwrap_or(Abi::C { unwind }), + abi => abi, } } @@ -1742,6 +1749,16 @@ impl Target { } } } ); + ($key_name:ident, Option<Abi>) => ( { + let name = (stringify!($key_name)).replace("_", "-"); + obj.find(&name[..]).and_then(|o| o.as_string().and_then(|s| { + match lookup_abi(s) { + Some(abi) => base.$key_name = Some(abi), + _ => return Some(Err(format!("'{}' is not a valid value for abi", s))), + } + Some(Ok(())) + })).unwrap_or(Ok(())) + } ); } if let Some(s) = obj.find("target-endian").and_then(Json::as_string) { @@ -1841,6 +1858,7 @@ impl Target { key!(has_thumb_interworking, bool); key!(split_debuginfo, SplitDebuginfo)?; key!(supported_sanitizers, SanitizerSet)?; + key!(default_adjusted_cabi, Option<Abi>)?; // NB: The old name is deprecated, but support for it is retained for // compatibility. @@ -2081,6 +2099,10 @@ impl ToJson for Target { target_option_val!(split_debuginfo); target_option_val!(supported_sanitizers); + if let Some(abi) = self.default_adjusted_cabi { + d.insert("default-adjusted-cabi".to_string(), Abi::name(abi).to_json()); + } + if default.unsupported_abis != self.unsupported_abis { d.insert( "unsupported-abis".to_string(), diff --git a/compiler/rustc_target/src/spec/wasm32_unknown_unknown.rs b/compiler/rustc_target/src/spec/wasm32_unknown_unknown.rs index 0a88ee42629..834c4dbfc05 100644 --- a/compiler/rustc_target/src/spec/wasm32_unknown_unknown.rs +++ b/compiler/rustc_target/src/spec/wasm32_unknown_unknown.rs @@ -12,11 +12,23 @@ use super::wasm_base; use super::{LinkerFlavor, LldFlavor, Target}; +use crate::spec::abi::Abi; pub fn target() -> Target { let mut options = wasm_base::options(); options.os = "unknown".to_string(); options.linker_flavor = LinkerFlavor::Lld(LldFlavor::Wasm); + + // 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); + let clang_args = options.pre_link_args.entry(LinkerFlavor::Gcc).or_default(); // Make sure clang uses LLD as its linker and is configured appropriately |
