Skip to content

Commit 7cf6260

Browse files
committed
work around the wasm32-unknown-unknown ABI being broken
1 parent c637bda commit 7cf6260

File tree

2 files changed

+47
-17
lines changed

2 files changed

+47
-17
lines changed

compiler/rustc_codegen_ssa/src/mir/naked_asm.rs

+38-9
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,10 @@ use rustc_middle::mir::mono::{Linkage, MonoItem, MonoItemData, Visibility};
44
use rustc_middle::mir::{Body, InlineAsmOperand};
55
use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt, HasTypingEnv, LayoutOf};
66
use rustc_middle::ty::{Instance, Ty, TyCtxt};
7-
use rustc_middle::{bug, ty};
8-
use rustc_span::sym;
7+
use rustc_middle::{bug, span_bug, ty};
8+
use rustc_span::{Span, sym};
99
use rustc_target::callconv::{ArgAbi, FnAbi, PassMode};
10+
use rustc_target::spec::WasmCAbi;
1011

1112
use crate::common;
1213
use crate::traits::{AsmCodegenMethods, BuilderMethods, GlobalAsmOperandRef, MiscCodegenMethods};
@@ -285,7 +286,12 @@ fn prefix_and_suffix<'tcx>(
285286
writeln!(begin, "{}", arch_prefix).unwrap();
286287
}
287288
writeln!(begin, "{asm_name}:").unwrap();
288-
writeln!(begin, ".functype {asm_name} {}", wasm_functype(tcx, fn_abi)).unwrap();
289+
writeln!(
290+
begin,
291+
".functype {asm_name} {}",
292+
wasm_functype(tcx, fn_abi, tcx.def_span(instance.def_id()))
293+
)
294+
.unwrap();
289295

290296
writeln!(end).unwrap();
291297
// .size is ignored for function symbols, so we can skip it
@@ -299,7 +305,7 @@ fn prefix_and_suffix<'tcx>(
299305
/// The webassembly type signature for the given function.
300306
///
301307
/// Used by the `.functype` directive on wasm targets.
302-
fn wasm_functype<'tcx>(tcx: TyCtxt<'tcx>, fn_abi: &FnAbi<'tcx, Ty<'tcx>>) -> String {
308+
fn wasm_functype<'tcx>(tcx: TyCtxt<'tcx>, fn_abi: &FnAbi<'tcx, Ty<'tcx>>, span: Span) -> String {
303309
let mut signature = String::with_capacity(64);
304310

305311
let ptr_type = match tcx.data_layout.pointer_size.bits() {
@@ -308,8 +314,18 @@ fn wasm_functype<'tcx>(tcx: TyCtxt<'tcx>, fn_abi: &FnAbi<'tcx, Ty<'tcx>>) -> Str
308314
other => bug!("wasm pointer size cannot be {other} bits"),
309315
};
310316

311-
let hidden_return =
312-
matches!(fn_abi.ret.mode, PassMode::Indirect { .. } | PassMode::Pair { .. });
317+
// FIXME: remove this once the wasm32-unknown-unknown ABI is fixed
318+
// please also add `wasm32-unknown-unknown` back in `tests/assembly/wasm32-naked-fn.rs`
319+
// basically the commit introducing this comment should be reverted
320+
if let PassMode::Pair { .. } = fn_abi.ret.mode {
321+
let _ = WasmCAbi::Legacy;
322+
span_bug!(
323+
span,
324+
"cannot return a pair (the wasm32-unknown-unknown ABI is broken, see https://github.com/rust-lang/rust/issues/115666"
325+
);
326+
}
327+
328+
let hidden_return = matches!(fn_abi.ret.mode, PassMode::Indirect { .. });
313329

314330
signature.push('(');
315331

@@ -322,7 +338,7 @@ fn wasm_functype<'tcx>(tcx: TyCtxt<'tcx>, fn_abi: &FnAbi<'tcx, Ty<'tcx>>) -> Str
322338

323339
let mut it = fn_abi.args.iter().peekable();
324340
while let Some(arg_abi) = it.next() {
325-
wasm_type(&mut signature, arg_abi, ptr_type);
341+
wasm_type(&mut signature, arg_abi, ptr_type, span);
326342
if it.peek().is_some() {
327343
signature.push_str(", ");
328344
}
@@ -331,21 +347,34 @@ fn wasm_functype<'tcx>(tcx: TyCtxt<'tcx>, fn_abi: &FnAbi<'tcx, Ty<'tcx>>) -> Str
331347
signature.push_str(") -> (");
332348

333349
if !hidden_return {
334-
wasm_type(&mut signature, &fn_abi.ret, ptr_type);
350+
wasm_type(&mut signature, &fn_abi.ret, ptr_type, span);
335351
}
336352

337353
signature.push(')');
338354

339355
signature
340356
}
341357

342-
fn wasm_type<'tcx>(signature: &mut String, arg_abi: &ArgAbi<'_, Ty<'tcx>>, ptr_type: &'static str) {
358+
fn wasm_type<'tcx>(
359+
signature: &mut String,
360+
arg_abi: &ArgAbi<'_, Ty<'tcx>>,
361+
ptr_type: &'static str,
362+
span: Span,
363+
) {
343364
match arg_abi.mode {
344365
PassMode::Ignore => { /* do nothing */ }
345366
PassMode::Direct(_) => {
346367
let direct_type = match arg_abi.layout.backend_repr {
347368
BackendRepr::Scalar(scalar) => wasm_primitive(scalar.primitive(), ptr_type),
348369
BackendRepr::Vector { .. } => "v128",
370+
BackendRepr::Memory { .. } => {
371+
// FIXME: remove this branch once the wasm32-unknown-unknown ABI is fixed
372+
let _ = WasmCAbi::Legacy;
373+
span_bug!(
374+
span,
375+
"cannot use memory args (the wasm32-unknown-unknown ABI is broken, see https://github.com/rust-lang/rust/issues/115666"
376+
);
377+
}
349378
other => unreachable!("unexpected BackendRepr: {:?}", other),
350379
};
351380

tests/assembly/wasm32-naked-fn.rs

+9-8
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
//@ revisions: wasm32-unknown wasm64-unknown wasm32-wasip1
1+
// FIXME: add wasm32-unknown when the wasm32-unknown-unknown ABI is fixed
2+
// see https://github.com/rust-lang/rust/issues/115666
3+
//@ revisions: wasm64-unknown wasm32-wasip1
24
//@ add-core-stubs
35
//@ assembly-output: emit-asm
4-
//@ [wasm32-unknown] compile-flags: --target wasm32-unknown-unknown
56
//@ [wasm64-unknown] compile-flags: --target wasm64-unknown-unknown
67
//@ [wasm32-wasip1] compile-flags: --target wasm32-wasip1
7-
//@ [wasm32-unknown] needs-llvm-components: webassembly
88
//@ [wasm64-unknown] needs-llvm-components: webassembly
99
//@ [wasm32-wasip1] needs-llvm-components: webassembly
1010

@@ -98,7 +98,7 @@ unsafe extern "C" fn fn_i64_i64(num: i64) -> i64 {
9898
}
9999

100100
// CHECK-LABEL: fn_i128_i128:
101-
// wasm32-unknown,wasm32-wasip1: .functype fn_i128_i128 (i32, i64, i64) -> ()
101+
// wasm32-wasip1: .functype fn_i128_i128 (i32, i64, i64) -> ()
102102
// wasm64-unknown: .functype fn_i128_i128 (i64, i64, i64) -> ()
103103
#[allow(improper_ctypes_definitions)]
104104
#[no_mangle]
@@ -115,7 +115,7 @@ unsafe extern "C" fn fn_i128_i128(num: i128) -> i128 {
115115
}
116116

117117
// CHECK-LABEL: fn_f128_f128:
118-
// wasm32-unknown,wasm32-wasip1: .functype fn_f128_f128 (i32, i64, i64) -> ()
118+
// wasm32-wasip1: .functype fn_f128_f128 (i32, i64, i64) -> ()
119119
// wasm64-unknown: .functype fn_f128_f128 (i64, i64, i64) -> ()
120120
#[no_mangle]
121121
#[naked]
@@ -138,18 +138,19 @@ struct Compound {
138138

139139
// CHECK-LABEL: fn_compound_compound:
140140
// wasm32-wasip1: .functype fn_compound_compound (i32, i32) -> ()
141-
// wasm32-unknown: .functype fn_compound_compound (i32, i32, i64) -> ()
142141
// wasm64-unknown: .functype fn_compound_compound (i64, i64) -> ()
143142
#[no_mangle]
144143
#[naked]
145144
unsafe extern "C" fn fn_compound_compound(_: Compound) -> Compound {
146-
// this is the wasm32-unknown-unknown assembly
145+
// this is the wasm32-wasip1 assembly
147146
naked_asm!(
148147
"local.get 0",
149-
"local.get 2",
148+
"local.get 1",
149+
"i64.load 8",
150150
"i64.store 8",
151151
"local.get 0",
152152
"local.get 1",
153+
"i32.load16_u 0",
153154
"i32.store16 0",
154155
)
155156
}

0 commit comments

Comments
 (0)