11use rustc_abi::{BackendRepr, Float, Integer, Primitive, RegKind};
22use rustc_attr_parsing::InstructionSetAttr;
3+ use rustc_hir::def_id::DefId;
34use rustc_middle::mir::mono::{Linkage, MonoItem, MonoItemData, Visibility};
45use rustc_middle::mir::{Body, InlineAsmOperand};
56use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt, HasTypingEnv, LayoutOf};
67use rustc_middle::ty::{Instance, Ty, TyCtxt};
7- use rustc_middle::{bug, ty};
8+ use rustc_middle::{bug, span_bug, ty};
89use rustc_span::sym;
910use rustc_target::callconv::{ArgAbi, FnAbi, PassMode};
11+ use rustc_target::spec::WasmCAbi;
1012
1113use crate::common;
1214use crate::traits::{AsmCodegenMethods, BuilderMethods, GlobalAsmOperandRef, MiscCodegenMethods};
@@ -285,7 +287,12 @@ fn prefix_and_suffix<'tcx>(
285287 writeln!(begin, "{}", arch_prefix).unwrap();
286288 }
287289 writeln!(begin, "{asm_name}:").unwrap();
288- writeln!(begin, ".functype {asm_name} {}", wasm_functype(tcx, fn_abi)).unwrap();
290+ writeln!(
291+ begin,
292+ ".functype {asm_name} {}",
293+ wasm_functype(tcx, fn_abi, instance.def_id())
294+ )
295+ .unwrap();
289296
290297 writeln!(end).unwrap();
291298 // .size is ignored for function symbols, so we can skip it
@@ -299,7 +306,7 @@ fn prefix_and_suffix<'tcx>(
299306/// The webassembly type signature for the given function.
300307///
301308/// Used by the `.functype` directive on wasm targets.
302- fn wasm_functype<'tcx>(tcx: TyCtxt<'tcx>, fn_abi: &FnAbi<'tcx, Ty<'tcx>>) -> String {
309+ fn wasm_functype<'tcx>(tcx: TyCtxt<'tcx>, fn_abi: &FnAbi<'tcx, Ty<'tcx>>, def_id: DefId ) -> String {
303310 let mut signature = String::with_capacity(64);
304311
305312 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
308315 other => bug!("wasm pointer size cannot be {other} bits"),
309316 };
310317
311- let hidden_return =
312- matches!(fn_abi.ret.mode, PassMode::Indirect { .. } | PassMode::Pair { .. });
318+ // FIXME: remove this once the wasm32-unknown-unknown ABI is fixed
319+ // please also add `wasm32-unknown-unknown` back in `tests/assembly/wasm32-naked-fn.rs`
320+ // basically the commit introducing this comment should be reverted
321+ if let PassMode::Pair { .. } = fn_abi.ret.mode {
322+ let _ = WasmCAbi::Legacy;
323+ span_bug!(
324+ tcx.def_span(def_id),
325+ "cannot return a pair (the wasm32-unknown-unknown ABI is broken, see https://github.com/rust-lang/rust/issues/115666"
326+ );
327+ }
328+
329+ let hidden_return = matches!(fn_abi.ret.mode, PassMode::Indirect { .. });
313330
314331 signature.push('(');
315332
@@ -322,7 +339,7 @@ fn wasm_functype<'tcx>(tcx: TyCtxt<'tcx>, fn_abi: &FnAbi<'tcx, Ty<'tcx>>) -> Str
322339
323340 let mut it = fn_abi.args.iter().peekable();
324341 while let Some(arg_abi) = it.next() {
325- wasm_type(&mut signature, arg_abi, ptr_type);
342+ wasm_type(tcx, &mut signature, arg_abi, ptr_type, def_id );
326343 if it.peek().is_some() {
327344 signature.push_str(", ");
328345 }
@@ -331,21 +348,35 @@ fn wasm_functype<'tcx>(tcx: TyCtxt<'tcx>, fn_abi: &FnAbi<'tcx, Ty<'tcx>>) -> Str
331348 signature.push_str(") -> (");
332349
333350 if !hidden_return {
334- wasm_type(&mut signature, &fn_abi.ret, ptr_type);
351+ wasm_type(tcx, &mut signature, &fn_abi.ret, ptr_type, def_id );
335352 }
336353
337354 signature.push(')');
338355
339356 signature
340357}
341358
342- fn wasm_type<'tcx>(signature: &mut String, arg_abi: &ArgAbi<'_, Ty<'tcx>>, ptr_type: &'static str) {
359+ fn wasm_type<'tcx>(
360+ tcx: TyCtxt<'tcx>,
361+ signature: &mut String,
362+ arg_abi: &ArgAbi<'_, Ty<'tcx>>,
363+ ptr_type: &'static str,
364+ def_id: DefId,
365+ ) {
343366 match arg_abi.mode {
344367 PassMode::Ignore => { /* do nothing */ }
345368 PassMode::Direct(_) => {
346369 let direct_type = match arg_abi.layout.backend_repr {
347370 BackendRepr::Scalar(scalar) => wasm_primitive(scalar.primitive(), ptr_type),
348371 BackendRepr::Vector { .. } => "v128",
372+ BackendRepr::Memory { .. } => {
373+ // FIXME: remove this branch once the wasm32-unknown-unknown ABI is fixed
374+ let _ = WasmCAbi::Legacy;
375+ span_bug!(
376+ tcx.def_span(def_id),
377+ "cannot use memory args (the wasm32-unknown-unknown ABI is broken, see https://github.com/rust-lang/rust/issues/115666"
378+ );
379+ }
349380 other => unreachable!("unexpected BackendRepr: {:?}", other),
350381 };
351382
0 commit comments