Skip to content

Commit

Permalink
Auto merge of #135534 - folkertdev:fix-wasm-i128-f128, r=tgross35
Browse files Browse the repository at this point in the history
use indirect return for `i128` and `f128` on wasm32

fixes #135532

Based on https://github.com/WebAssembly/tool-conventions/blob/main/BasicCABI.md we now use an indirect return for  `i128`, `u128` and `f128`. That is what LLVM ended up doing anyway.

r? `@bjorn3`
  • Loading branch information
bors committed Jan 17, 2025
2 parents 73c0ae6 + 702134a commit bcd0683
Show file tree
Hide file tree
Showing 3 changed files with 110 additions and 0 deletions.
12 changes: 12 additions & 0 deletions compiler/rustc_target/src/callconv/wasm.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use rustc_abi::{BackendRepr, Float, Integer, Primitive};

use crate::abi::call::{ArgAbi, FnAbi};
use crate::abi::{HasDataLayout, TyAbiInterface};

Expand Down Expand Up @@ -27,6 +29,16 @@ where
if ret.layout.is_aggregate() && !unwrap_trivial_aggregate(cx, ret) {
ret.make_indirect();
}

// `long double`, `__int128_t` and `__uint128_t` use an indirect return
if let BackendRepr::Scalar(scalar) = ret.layout.backend_repr {
match scalar.primitive() {
Primitive::Int(Integer::I128, _) | Primitive::Float(Float::F128) => {
ret.make_indirect();
}
_ => {}
}
}
}

fn classify_arg<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>)
Expand Down
49 changes: 49 additions & 0 deletions tests/codegen/f128-wasm32-callconv.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
//! Verify that Rust implements the expected calling convention for `f128`
//@ add-core-stubs
//@ compile-flags: -O --target wasm32-wasip1
//@ needs-llvm-components: webassembly

#![crate_type = "lib"]
#![no_std]
#![no_core]
#![feature(no_core, lang_items, f128)]

extern crate minicore;

extern "C" {
fn extern_call(arg0: f128);
fn extern_ret() -> f128;
}

#[no_mangle]
pub extern "C" fn pass(_arg0: u32, arg1: f128) {
// CHECK-LABEL: @pass(
// an f128 is passed via registers
// CHECK-SAME: fp128 noundef %arg1
// CHECK: call void @extern_call
unsafe { extern_call(arg1) };
}

// Check that we produce the correct return ABI
#[no_mangle]
pub extern "C" fn ret(_arg0: u32, arg1: f128) -> f128 {
// CHECK-LABEL: @ret(
// but an f128 is returned via the stack
// CHECK-SAME: sret
// CHECK: store fp128 %arg1
// CHECK-NEXT: ret void
arg1
}

// Check that we consume the correct return ABI
#[no_mangle]
pub extern "C" fn forward(dst: *mut f128) {
// CHECK-LABEL: @forward
// CHECK-SAME: ptr{{.*}} %dst)
// without optimizatons, an intermediate alloca is used
// CHECK: call void @extern_ret
// CHECK: store fp128
// CHECK: ret void
unsafe { *dst = extern_ret() };
}
49 changes: 49 additions & 0 deletions tests/codegen/i128-wasm32-callconv.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
//! Verify that Rust implements the expected calling convention for `i128`/`u128`.
//@ add-core-stubs
//@ compile-flags: -O --target wasm32-wasip1
//@ needs-llvm-components: webassembly

#![crate_type = "lib"]
#![no_std]
#![no_core]
#![feature(no_core, lang_items)]

extern crate minicore;

extern "C" {
fn extern_call(arg0: i128);
fn extern_ret() -> i128;
}

#[no_mangle]
pub extern "C" fn pass(_arg0: u32, arg1: i128) {
// CHECK-LABEL: @pass(
// an i128 is passed via registers
// CHECK-SAME: i128 noundef %arg1
// CHECK: call void @extern_call
unsafe { extern_call(arg1) };
}

// Check that we produce the correct return ABI
#[no_mangle]
pub extern "C" fn ret(_arg0: u32, arg1: i128) -> i128 {
// CHECK-LABEL: @ret(
// but an i128 is returned via the stack
// CHECK-SAME: sret
// CHECK: store i128 %arg1
// CHECK-NEXT: ret void
arg1
}

// Check that we consume the correct return ABI
#[no_mangle]
pub extern "C" fn forward(dst: *mut i128) {
// CHECK-LABEL: @forward
// CHECK-SAME: ptr{{.*}} %dst)
// without optimizatons, an intermediate alloca is used
// CHECK: call void @extern_ret
// CHECK: store i128
// CHECK: ret void
unsafe { *dst = extern_ret() };
}

0 comments on commit bcd0683

Please sign in to comment.