From 269582738617cd549b484640ebada164bc146bd3 Mon Sep 17 00:00:00 2001 From: Heejin Ahn Date: Tue, 19 Mar 2024 01:21:49 +0000 Subject: [PATCH] [BasicCABI] Pass compiler-rt 128-bit return values in memory Currently our LLVM Wasm backend returns 128-bit values as two `i64`s in case multivalue is enabled: https://github.com/llvm/llvm-project/blob/a5f576e5961ecc099bd7ccf8565da090edc84b0d/llvm/lib/Target/WebAssembly/WebAssemblyRuntimeLibcallSignatures.cpp#L697-L700 But given that neither emscripten nor wasm-sdk seem to provide a multivalue version of compiler-rt, it looks this has not been working so far and the reason we haven't heard complaints was likely that no one was using compiler-rt with multivalue enabled. Maintaining and providing two different versions of compiler-rt is a cumbersome thing for toolchains, and emscripten already has to provide multiple versions of many libraries (e.g. threaded vs. non-threaded, debug vs. release, exception-enabled vs. disabled, ...). Also enabling the multivalue return on several compiler-rt functions that have a 128-bit return value wouldn't affect performance in a meaningful way, given that there are not many of them. I had a chance to chat with several people who contribute here offline this morning, and it looked we agreed that there is not much benefit to enabling multivalue return in compiler-rt functions. One thing I'm not sure is whether we decided to disable 128-bit multivalue returns for only compiler-rt functions or for all user functions. This PR currently says we do that only for compiler-rt; please let me know if you think we should do otherwise. --- BasicCABI.md | 40 ++++++++++++++++++++++++++-------------- 1 file changed, 26 insertions(+), 14 deletions(-) diff --git a/BasicCABI.md b/BasicCABI.md index 6119bde..63b8033 100644 --- a/BasicCABI.md +++ b/BasicCABI.md @@ -173,23 +173,35 @@ making a copy of any indirectly passed data that the callee should not modify. Similarly, types can either be returned directly from WebAssembly functions or returned indirectly via a pointer parameter prepended to the parameter list. -Type | Parameter | Result | ------------------------------|---------------|----------| -scalar[1] | direct | direct | -empty struct or union | ignored | ignored | -singleton struct or union[2] | direct | direct | -other struct or union[3] | indirect | indirect | -array | indirect | N/A | - -[1] `long long double` and `__int128` are passed directly as two `i64` values. -Signed 8 and 16-bit scalars are sign-extended, and unsigned 8 and 16-bit -scalars are zero-extended before passing or returning. - -[2] Any struct or union that recursively (including through nested structs, +Type | Parameter | Result | +-----------------------------|---------------|--------------------| +scalar | direct[1] | direct/indirect[2] | +empty struct or union | ignored | ignored | +singleton struct or union[3] | direct | direct | +other struct or union[4] | indirect | indirect | +array | indirect | N/A | + +[1] In case of parameters, `long long double`, `__int128`, and `__float128` are +passed directly as two `i64` values. In case of return values, for +non-compiler-rt functions, they are passed directly as two `i64` values if +[multivalue](https://github.com/WebAssembly/multi-value) is enabled and +indirectly passed via a pointer parameter otherwise. +Signed 8 and 16-bit scalars are sign-extended, and unsigned 8 and 16-bit scalars +are zero-extended before passing or returning. + +[2] In case of return values for compiler-rt functions, `long long double`, +`__int128`, and `__float128` are indirectly passed via a pointer parameter that +points to the value in memory, regardless of whether +[multivalue](https://github.com/WebAssembly/multi-value) is enabled or not, to +make the compiler-rt ABI uniform across the features. +Signed 8 and 16-bit scalars are sign-extended, and unsigned 8 and 16-bit scalars +are zero-extended before passing or returning. + +[3] Any struct or union that recursively (including through nested structs, unions, and arrays) contains just a single scalar value and is not specified to have greater than natural alignment. -[3] This calling convention was defined before +[4] This calling convention was defined before [multivalue](https://github.com/WebAssembly/multi-value) was standardized. A new default calling convention that changes this behavior and takes advantage of multivalue may be introduced in the future.