Wasm modules can have funcs with more than 16 params
- 主要言語
- Rust
- スター
- 115
- フォーク
- 84
- 平均マージ
- 1日 8時間
- マージ済み PR(30日)
- 15
説明
Wasm's component model [defines](https://github.com/WebAssembly/component-model/blob/main/design/mvp/CanonicalABI.md#flattening):
```
MAX_FLAT_PARAMS = 16
```
My understanding is that this limit applies *only at component boundaries*. Meaning a component may still have functions with more than 16 parameters, as long as they don't cross the component boundary. See below for a reproduction.
The number of function parameters for core Wasm *may* be restricted ([ref](https://webassembly.github.io/spec/core/appendix/implementation.html#structure)):
```
An implementation may impose restrictions on the following dimensions of a module:
[...]
- the number of parameters in a function type
[...]
```
On a quick search I couldn't find a limit in llvm's Wasm backend. For reference, 1000 function parameters seems to be a limit enforced in practice by [wasmparser](https://github.com/bytecodealliance/wasm-tools/blob/e2d3556ae7aec4acd26a0695c7905930db45753d/crates/wasmparser/src/limits.rs#L33) and [js-api](https://webassembly.github.io/spec/js-api/?utm_source=chatgpt.com#limits).
However `midenc` currently cannot generate function calls with more than 16 parameters since all parameters are passed on the stack of Miden VM.
### Why not surfaced so far
I suppose because with `panic=immediate-abort` formatting code is eliminated and usually nobody writes functions with `>16` parameters.
### Reproduction
```sh
# In the root of the repo
cargo make midenc cargo-miden
# Build script needs to find these binaries
export PATH="$(pwd)/bin:$PATH"
# Place the attached files in `examples/wide-fn-call`
cd examples/wide-fn-call
# debug build with `panic=abort`
RUSTFLAGS="-C panic=abort" ../../bin/midenc --entrypoint wide_fn_call::entrypoint miden-project.toml
thread 'main' (30352) panicked at hir-analysis/src/analyses/spills.rs:2366:21:
unable to spill sufficient capacity to hold all operands on stack at one time at %93 = hir.exec ::@root_ns:root@1.0.0::@wide_fn_call::@_RNvMsa_NtCs5PnfH09bhDl_4core3fmtNtB5_9Formatter26debug_struct_field5_finish(%62, %3591, %3590, %3589, %3588, %67, %3587, %3586, %3588, %73, %3587, %3584, %3588, %79, %3587, %3582, %3588, %85, %3587, %3580, %3588, %91, %3579) : extern("C") (i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32) -> i32;
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
```
#### Wasm inspection
```sh
cargo build --target wasm32-wasip1
wasm-tools print target/wasm32-wasip1/debug/wide_fn_call.wasm > wide_fn_call.wat
```
In `wide_fn_call.wat` search for `debug_struct_field5_finish`.
[`debug_struct_field5_finish`](https://github.com/rust-lang/rust/blob/70222712809cd5cc1718ed8995914a1cbacb6b92/library/core/src/fmt/mod.rs#L2539) is an optimization related to `Debug` formatting of structs with 5 fields. There are no equivalents for structs with more than 5 fields, so this issue might not be hit if the struct had 6 fields. A potential short-term band-aid would be providing another `Debug` implementation. Though of course that doesn't help with calling functions with more than 16 parameters in general.
### How to support more than 16 params?
Spill or generate wrappers with at most 16 params?
[wide-fn-call.tar.gz](https://github.com/user-attachments/files/31689150/wide-fn-call.tar.gz)
コントリビューションガイド
調査の方向性
The issue is in the compiler's spill handling for functions with >16 parameters, as shown in the error from hir-analysis/src/analyses/spills.rs. Examine the attached wide-fn-call example to understand the reproduction. Look at how parameters are passed on the Miden VM stack and consider implementing spilling or wrapper generation. Testing involves building with the provided commands and checking the wasm output.
索引モデルが issue の本文から書いたものです。
評価
- 技術スタック
- rust, wasm
- 領域
- compilers
- issue の種類
- バグ
- 難易度
- 4/5
- 見積もり時間
- 3〜5日
- 活発さ
- 活発
- 明瞭さ
- 明確に書かれている
- 初心者へのやさしさ
- 40/100