rust/tests/assembly/wasm32-naked-fn.rs

200 lines
5.0 KiB
Rust

// 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
//@ [wasm64-unknown] compile-flags: --target wasm64-unknown-unknown
//@ [wasm32-wasip1] compile-flags: --target wasm32-wasip1
//@ [wasm64-unknown] needs-llvm-components: webassembly
//@ [wasm32-wasip1] needs-llvm-components: webassembly
#![crate_type = "lib"]
#![feature(no_core, naked_functions, asm_experimental_arch, f128, linkage, fn_align)]
#![no_core]
extern crate minicore;
use minicore::*;
// CHECK: .section .text.nop,"",@
// CHECK: .globl nop
// CHECK-LABEL: nop:
// CHECK: .functype nop () -> ()
// CHECK-NOT: .size
// CHECK: end_function
#[no_mangle]
#[naked]
unsafe extern "C" fn nop() {
naked_asm!("nop")
}
// CHECK: .section .text.weak_aligned_nop,"",@
// CHECK: .weak weak_aligned_nop
// CHECK-LABEL: nop:
// CHECK: .functype weak_aligned_nop () -> ()
// CHECK-NOT: .size
// CHECK: end_function
#[no_mangle]
#[naked]
#[linkage = "weak"]
// wasm functions cannot be aligned, so this has no effect
#[repr(align(32))]
unsafe extern "C" fn weak_aligned_nop() {
naked_asm!("nop")
}
// CHECK-LABEL: fn_i8_i8:
// CHECK-NEXT: .functype fn_i8_i8 (i32) -> (i32)
//
// CHECK-NEXT: local.get 0
// CHECK-NEXT: local.get 0
// CHECK-NEXT: i32.mul
//
// CHECK-NEXT: end_function
#[no_mangle]
#[naked]
unsafe extern "C" fn fn_i8_i8(num: i8) -> i8 {
naked_asm!("local.get 0", "local.get 0", "i32.mul")
}
// CHECK-LABEL: fn_i8_i8_i8:
// CHECK: .functype fn_i8_i8_i8 (i32, i32) -> (i32)
#[no_mangle]
#[naked]
unsafe extern "C" fn fn_i8_i8_i8(a: i8, b: i8) -> i8 {
naked_asm!("local.get 1", "local.get 0", "i32.mul")
}
// CHECK-LABEL: fn_unit_i8:
// CHECK: .functype fn_unit_i8 () -> (i32)
#[no_mangle]
#[naked]
unsafe extern "C" fn fn_unit_i8() -> i8 {
naked_asm!("i32.const 42")
}
// CHECK-LABEL: fn_i8_unit:
// CHECK: .functype fn_i8_unit (i32) -> ()
#[no_mangle]
#[naked]
unsafe extern "C" fn fn_i8_unit(_: i8) {
naked_asm!("nop")
}
// CHECK-LABEL: fn_i32_i32:
// CHECK: .functype fn_i32_i32 (i32) -> (i32)
#[no_mangle]
#[naked]
unsafe extern "C" fn fn_i32_i32(num: i32) -> i32 {
naked_asm!("local.get 0", "local.get 0", "i32.mul")
}
// CHECK-LABEL: fn_i64_i64:
// CHECK: .functype fn_i64_i64 (i64) -> (i64)
#[no_mangle]
#[naked]
unsafe extern "C" fn fn_i64_i64(num: i64) -> i64 {
naked_asm!("local.get 0", "local.get 0", "i64.mul")
}
// CHECK-LABEL: fn_i128_i128:
// wasm32-wasip1: .functype fn_i128_i128 (i32, i64, i64) -> ()
// wasm64-unknown: .functype fn_i128_i128 (i64, i64, i64) -> ()
#[allow(improper_ctypes_definitions)]
#[no_mangle]
#[naked]
unsafe extern "C" fn fn_i128_i128(num: i128) -> i128 {
naked_asm!(
"local.get 0",
"local.get 2",
"i64.store 8",
"local.get 0",
"local.get 1",
"i64.store 0",
)
}
// CHECK-LABEL: fn_f128_f128:
// wasm32-wasip1: .functype fn_f128_f128 (i32, i64, i64) -> ()
// wasm64-unknown: .functype fn_f128_f128 (i64, i64, i64) -> ()
#[no_mangle]
#[naked]
unsafe extern "C" fn fn_f128_f128(num: f128) -> f128 {
naked_asm!(
"local.get 0",
"local.get 2",
"i64.store 8",
"local.get 0",
"local.get 1",
"i64.store 0",
)
}
#[repr(C)]
struct Compound {
a: u16,
b: i64,
}
// CHECK-LABEL: fn_compound_compound:
// wasm32-wasip1: .functype fn_compound_compound (i32, i32) -> ()
// wasm64-unknown: .functype fn_compound_compound (i64, i64) -> ()
#[no_mangle]
#[naked]
unsafe extern "C" fn fn_compound_compound(_: Compound) -> Compound {
// this is the wasm32-wasip1 assembly
naked_asm!(
"local.get 0",
"local.get 1",
"i64.load 8",
"i64.store 8",
"local.get 0",
"local.get 1",
"i32.load16_u 0",
"i32.store16 0",
)
}
#[repr(C)]
struct WrapperI32(i32);
// CHECK-LABEL: fn_wrapperi32_wrapperi32:
// CHECK: .functype fn_wrapperi32_wrapperi32 (i32) -> (i32)
#[no_mangle]
#[naked]
unsafe extern "C" fn fn_wrapperi32_wrapperi32(_: WrapperI32) -> WrapperI32 {
naked_asm!("local.get 0")
}
#[repr(C)]
struct WrapperI64(i64);
// CHECK-LABEL: fn_wrapperi64_wrapperi64:
// CHECK: .functype fn_wrapperi64_wrapperi64 (i64) -> (i64)
#[no_mangle]
#[naked]
unsafe extern "C" fn fn_wrapperi64_wrapperi64(_: WrapperI64) -> WrapperI64 {
naked_asm!("local.get 0")
}
#[repr(C)]
struct WrapperF32(f32);
// CHECK-LABEL: fn_wrapperf32_wrapperf32:
// CHECK: .functype fn_wrapperf32_wrapperf32 (f32) -> (f32)
#[no_mangle]
#[naked]
unsafe extern "C" fn fn_wrapperf32_wrapperf32(_: WrapperF32) -> WrapperF32 {
naked_asm!("local.get 0")
}
#[repr(C)]
struct WrapperF64(f64);
// CHECK-LABEL: fn_wrapperf64_wrapperf64:
// CHECK: .functype fn_wrapperf64_wrapperf64 (f64) -> (f64)
#[no_mangle]
#[naked]
unsafe extern "C" fn fn_wrapperf64_wrapperf64(_: WrapperF64) -> WrapperF64 {
naked_asm!("local.get 0")
}