diff options
| author | Folkert de Vries <folkert@folkertdev.nl> | 2025-01-17 22:34:26 +0100 |
|---|---|---|
| committer | Folkert de Vries <folkert@folkertdev.nl> | 2025-01-20 16:57:09 +0100 |
| commit | bcf478b7a6915a8ce14009934f2893ddcce8052c (patch) | |
| tree | 38566a85b80106a50ba7b7fa714e6c5e1d8e2bf8 | |
| parent | 8dec09f3c5bf8e1f12c6ba6eb6040d710353ca63 (diff) | |
| download | rust-bcf478b7a6915a8ce14009934f2893ddcce8052c.tar.gz rust-bcf478b7a6915a8ce14009934f2893ddcce8052c.zip | |
work around the `wasm32-unknown-unknown` ABI being broken
| -rw-r--r-- | compiler/rustc_codegen_ssa/src/mir/naked_asm.rs | 47 | ||||
| -rw-r--r-- | tests/assembly/wasm32-naked-fn.rs | 17 |
2 files changed, 48 insertions, 16 deletions
diff --git a/compiler/rustc_codegen_ssa/src/mir/naked_asm.rs b/compiler/rustc_codegen_ssa/src/mir/naked_asm.rs index 35e0ea54525..dc406809874 100644 --- a/compiler/rustc_codegen_ssa/src/mir/naked_asm.rs +++ b/compiler/rustc_codegen_ssa/src/mir/naked_asm.rs @@ -1,12 +1,14 @@ use rustc_abi::{BackendRepr, Float, Integer, Primitive, RegKind}; use rustc_attr_parsing::InstructionSetAttr; +use rustc_hir::def_id::DefId; use rustc_middle::mir::mono::{Linkage, MonoItem, MonoItemData, Visibility}; use rustc_middle::mir::{Body, InlineAsmOperand}; use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt, HasTypingEnv, LayoutOf}; use rustc_middle::ty::{Instance, Ty, TyCtxt}; -use rustc_middle::{bug, ty}; +use rustc_middle::{bug, span_bug, ty}; use rustc_span::sym; use rustc_target::callconv::{ArgAbi, FnAbi, PassMode}; +use rustc_target::spec::WasmCAbi; use crate::common; use crate::traits::{AsmCodegenMethods, BuilderMethods, GlobalAsmOperandRef, MiscCodegenMethods}; @@ -285,7 +287,12 @@ fn prefix_and_suffix<'tcx>( writeln!(begin, "{}", arch_prefix).unwrap(); } writeln!(begin, "{asm_name}:").unwrap(); - writeln!(begin, ".functype {asm_name} {}", wasm_functype(tcx, fn_abi)).unwrap(); + writeln!( + begin, + ".functype {asm_name} {}", + wasm_functype(tcx, fn_abi, instance.def_id()) + ) + .unwrap(); writeln!(end).unwrap(); // .size is ignored for function symbols, so we can skip it @@ -299,7 +306,7 @@ fn prefix_and_suffix<'tcx>( /// The webassembly type signature for the given function. /// /// Used by the `.functype` directive on wasm targets. -fn wasm_functype<'tcx>(tcx: TyCtxt<'tcx>, fn_abi: &FnAbi<'tcx, Ty<'tcx>>) -> String { +fn wasm_functype<'tcx>(tcx: TyCtxt<'tcx>, fn_abi: &FnAbi<'tcx, Ty<'tcx>>, def_id: DefId) -> String { let mut signature = String::with_capacity(64); let ptr_type = match tcx.data_layout.pointer_size.bits() { @@ -308,8 +315,18 @@ fn wasm_functype<'tcx>(tcx: TyCtxt<'tcx>, fn_abi: &FnAbi<'tcx, Ty<'tcx>>) -> Str other => bug!("wasm pointer size cannot be {other} bits"), }; - let hidden_return = - matches!(fn_abi.ret.mode, PassMode::Indirect { .. } | PassMode::Pair { .. }); + // FIXME: remove this once the wasm32-unknown-unknown ABI is fixed + // please also add `wasm32-unknown-unknown` back in `tests/assembly/wasm32-naked-fn.rs` + // basically the commit introducing this comment should be reverted + if let PassMode::Pair { .. } = fn_abi.ret.mode { + let _ = WasmCAbi::Legacy; + span_bug!( + tcx.def_span(def_id), + "cannot return a pair (the wasm32-unknown-unknown ABI is broken, see https://github.com/rust-lang/rust/issues/115666" + ); + } + + let hidden_return = matches!(fn_abi.ret.mode, PassMode::Indirect { .. }); signature.push('('); @@ -322,7 +339,7 @@ fn wasm_functype<'tcx>(tcx: TyCtxt<'tcx>, fn_abi: &FnAbi<'tcx, Ty<'tcx>>) -> Str let mut it = fn_abi.args.iter().peekable(); while let Some(arg_abi) = it.next() { - wasm_type(&mut signature, arg_abi, ptr_type); + wasm_type(tcx, &mut signature, arg_abi, ptr_type, def_id); if it.peek().is_some() { signature.push_str(", "); } @@ -331,7 +348,7 @@ fn wasm_functype<'tcx>(tcx: TyCtxt<'tcx>, fn_abi: &FnAbi<'tcx, Ty<'tcx>>) -> Str signature.push_str(") -> ("); if !hidden_return { - wasm_type(&mut signature, &fn_abi.ret, ptr_type); + wasm_type(tcx, &mut signature, &fn_abi.ret, ptr_type, def_id); } signature.push(')'); @@ -339,13 +356,27 @@ fn wasm_functype<'tcx>(tcx: TyCtxt<'tcx>, fn_abi: &FnAbi<'tcx, Ty<'tcx>>) -> Str signature } -fn wasm_type<'tcx>(signature: &mut String, arg_abi: &ArgAbi<'_, Ty<'tcx>>, ptr_type: &'static str) { +fn wasm_type<'tcx>( + tcx: TyCtxt<'tcx>, + signature: &mut String, + arg_abi: &ArgAbi<'_, Ty<'tcx>>, + ptr_type: &'static str, + def_id: DefId, +) { match arg_abi.mode { PassMode::Ignore => { /* do nothing */ } PassMode::Direct(_) => { let direct_type = match arg_abi.layout.backend_repr { BackendRepr::Scalar(scalar) => wasm_primitive(scalar.primitive(), ptr_type), BackendRepr::Vector { .. } => "v128", + BackendRepr::Memory { .. } => { + // FIXME: remove this branch once the wasm32-unknown-unknown ABI is fixed + let _ = WasmCAbi::Legacy; + span_bug!( + tcx.def_span(def_id), + "cannot use memory args (the wasm32-unknown-unknown ABI is broken, see https://github.com/rust-lang/rust/issues/115666" + ); + } other => unreachable!("unexpected BackendRepr: {:?}", other), }; diff --git a/tests/assembly/wasm32-naked-fn.rs b/tests/assembly/wasm32-naked-fn.rs index 8e98b084729..4911a6bd08f 100644 --- a/tests/assembly/wasm32-naked-fn.rs +++ b/tests/assembly/wasm32-naked-fn.rs @@ -1,10 +1,10 @@ -//@ revisions: wasm32-unknown wasm64-unknown wasm32-wasip1 +// FIXME: add wasm32-unknown when the wasm32-unknown-unknown ABI is fixed +// see https://github.com/rust-lang/rust/issues/115666 +//@ revisions: wasm64-unknown wasm32-wasip1 //@ add-core-stubs //@ assembly-output: emit-asm -//@ [wasm32-unknown] compile-flags: --target wasm32-unknown-unknown //@ [wasm64-unknown] compile-flags: --target wasm64-unknown-unknown //@ [wasm32-wasip1] compile-flags: --target wasm32-wasip1 -//@ [wasm32-unknown] needs-llvm-components: webassembly //@ [wasm64-unknown] needs-llvm-components: webassembly //@ [wasm32-wasip1] needs-llvm-components: webassembly @@ -97,7 +97,7 @@ unsafe extern "C" fn fn_i64_i64(num: i64) -> i64 { } // CHECK-LABEL: fn_i128_i128: -// wasm32-unknown,wasm32-wasip1: .functype fn_i128_i128 (i32, i64, i64) -> () +// wasm32-wasip1: .functype fn_i128_i128 (i32, i64, i64) -> () // wasm64-unknown: .functype fn_i128_i128 (i64, i64, i64) -> () #[allow(improper_ctypes_definitions)] #[no_mangle] @@ -114,7 +114,7 @@ unsafe extern "C" fn fn_i128_i128(num: i128) -> i128 { } // CHECK-LABEL: fn_f128_f128: -// wasm32-unknown,wasm32-wasip1: .functype fn_f128_f128 (i32, i64, i64) -> () +// wasm32-wasip1: .functype fn_f128_f128 (i32, i64, i64) -> () // wasm64-unknown: .functype fn_f128_f128 (i64, i64, i64) -> () #[no_mangle] #[naked] @@ -137,18 +137,19 @@ struct Compound { // CHECK-LABEL: fn_compound_compound: // wasm32-wasip1: .functype fn_compound_compound (i32, i32) -> () -// wasm32-unknown: .functype fn_compound_compound (i32, i32, i64) -> () // wasm64-unknown: .functype fn_compound_compound (i64, i64) -> () #[no_mangle] #[naked] unsafe extern "C" fn fn_compound_compound(_: Compound) -> Compound { - // this is the wasm32-unknown-unknown assembly + // this is the wasm32-wasip1 assembly naked_asm!( "local.get 0", - "local.get 2", + "local.get 1", + "i64.load 8", "i64.store 8", "local.get 0", "local.get 1", + "i32.load16_u 0", "i32.store16 0", ) } |
