Skip to content

Commit 1e6d533

Browse files
authored
Fix argument extension on riscv64 for Wasmtime builtins (bytecodealliance#10069)
* Fix argument extension on riscv64 for Wasmtime builtins This commit fixes a crash found in the CI of bytecodealliance#10040. That PR itself isn't the fault per-se but rather uncovered a preexisting issue on riscv64. According to riscv64's ABI docs it looks like arguments are all expected to be sign-extended, whereas currently in Wasmtime all host signatures are zero-extended on all platforms. This commit applies two changes to fix this: * A new `TargetIsa::default_argument_extension` method was added which is now used instead of unconditionally using `uext` to apply to all arguments/results. * While I was here I went ahead and split apart things where the wasm signature of a builtin doesn't use `uext` or `sext`. The host signature still does, however, which means that any extension necessary happens in the trampoline we generate per-libcall as opposed to at all callsites. I'm not certain that all platforms require `uext` but I've left the `TargetIsa` implementation as `uext` for now with a comment explaining why. Currently the only non-`uext` platforms are riscv64, which is `sext` to fix the issue from bytecodealliance#10040, and Pulley which is "none" as things work differently there. * Update test expectations
1 parent 392c7a9 commit 1e6d533

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+124
-61
lines changed

cranelift/codegen/src/isa/aarch64/mod.rs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
//! ARM 64-bit Instruction Set Architecture.
22
33
use crate::dominator_tree::DominatorTree;
4-
use crate::ir::{Function, Type};
4+
use crate::ir::{self, Function, Type};
55
use crate::isa::aarch64::settings as aarch64_settings;
66
#[cfg(feature = "unwind")]
77
use crate::isa::unwind::systemv;
@@ -238,6 +238,17 @@ impl TargetIsa for AArch64Backend {
238238
fn has_x86_pmaddubsw_lowering(&self) -> bool {
239239
false
240240
}
241+
242+
fn default_argument_extension(&self) -> ir::ArgumentExtension {
243+
// This is copied/carried over from a historical piece of code in
244+
// Wasmtime:
245+
//
246+
// https://github.com/bytecodealliance/wasmtime/blob/a018a5a9addb77d5998021a0150192aa955c71bf/crates/cranelift/src/lib.rs#L366-L374
247+
//
248+
// Whether or not it is still applicable here is unsure, but it's left
249+
// the same as-is for now to reduce the likelihood of problems arising.
250+
ir::ArgumentExtension::Uext
251+
}
241252
}
242253

243254
impl fmt::Display for AArch64Backend {

cranelift/codegen/src/isa/mod.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -400,6 +400,16 @@ pub trait TargetIsa: fmt::Display + Send + Sync {
400400
/// Returns whether the CLIF `x86_pmaddubsw` instruction is implemented for
401401
/// this ISA.
402402
fn has_x86_pmaddubsw_lowering(&self) -> bool;
403+
404+
/// Returns the mode of extension used for integer arguments smaller than
405+
/// the pointer width in function signatures.
406+
///
407+
/// Some platform ABIs require that smaller-than-pointer-width values are
408+
/// either zero or sign-extended to the full register width. This value is
409+
/// propagated to the `AbiParam` value created for signatures. Note that not
410+
/// all ABIs for all platforms require extension of any form, so this is
411+
/// generally only necessary for the `default_call_conv`.
412+
fn default_argument_extension(&self) -> ir::ArgumentExtension;
403413
}
404414

405415
/// Function alignment specifications as required by an ISA, returned by

cranelift/codegen/src/isa/pulley_shared/mod.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,10 @@ where
243243
fn has_x86_pmaddubsw_lowering(&self) -> bool {
244244
false
245245
}
246+
247+
fn default_argument_extension(&self) -> ir::ArgumentExtension {
248+
ir::ArgumentExtension::None
249+
}
246250
}
247251

248252
/// Create a new Pulley ISA builder.

cranelift/codegen/src/isa/riscv64/mod.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,19 @@ impl TargetIsa for Riscv64Backend {
216216
fn has_x86_pmaddubsw_lowering(&self) -> bool {
217217
false
218218
}
219+
220+
fn default_argument_extension(&self) -> ir::ArgumentExtension {
221+
// According to https://riscv.org/wp-content/uploads/2024/12/riscv-calling.pdf
222+
// it says:
223+
//
224+
// > In RV64, 32-bit types, such as int, are stored in integer
225+
// > registers as proper sign extensions of their 32-bit values; that
226+
// > is, bits 63..31 are all equal. This restriction holds even for
227+
// > unsigned 32-bit types.
228+
//
229+
// leading to `sext` here.
230+
ir::ArgumentExtension::Sext
231+
}
219232
}
220233

221234
impl fmt::Display for Riscv64Backend {

cranelift/codegen/src/isa/s390x/mod.rs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
//! IBM Z 64-bit Instruction Set Architecture.
22
33
use crate::dominator_tree::DominatorTree;
4-
use crate::ir::{Function, Type};
4+
use crate::ir::{self, Function, Type};
55
use crate::isa::s390x::settings as s390x_settings;
66
#[cfg(feature = "unwind")]
77
use crate::isa::unwind::systemv::RegisterMappingError;
@@ -198,6 +198,17 @@ impl TargetIsa for S390xBackend {
198198
fn has_x86_pmaddubsw_lowering(&self) -> bool {
199199
false
200200
}
201+
202+
fn default_argument_extension(&self) -> ir::ArgumentExtension {
203+
// This is copied/carried over from a historical piece of code in
204+
// Wasmtime:
205+
//
206+
// https://github.com/bytecodealliance/wasmtime/blob/a018a5a9addb77d5998021a0150192aa955c71bf/crates/cranelift/src/lib.rs#L366-L374
207+
//
208+
// Whether or not it is still applicable here is unsure, but it's left
209+
// the same as-is for now to reduce the likelihood of problems arising.
210+
ir::ArgumentExtension::Uext
211+
}
201212
}
202213

203214
impl fmt::Display for S390xBackend {

cranelift/codegen/src/isa/x64/mod.rs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ pub use self::inst::{args, AtomicRmwSeqOp, EmitInfo, EmitState, Inst};
44

55
use super::{OwnedTargetIsa, TargetIsa};
66
use crate::dominator_tree::DominatorTree;
7-
use crate::ir::{types, Function, Type};
7+
use crate::ir::{self, types, Function, Type};
88
#[cfg(feature = "unwind")]
99
use crate::isa::unwind::systemv;
1010
use crate::isa::x64::settings as x64_settings;
@@ -186,6 +186,17 @@ impl TargetIsa for X64Backend {
186186
fn has_x86_pmaddubsw_lowering(&self) -> bool {
187187
self.x64_flags.use_ssse3()
188188
}
189+
190+
fn default_argument_extension(&self) -> ir::ArgumentExtension {
191+
// This is copied/carried over from a historical piece of code in
192+
// Wasmtime:
193+
//
194+
// https://github.com/bytecodealliance/wasmtime/blob/a018a5a9addb77d5998021a0150192aa955c71bf/crates/cranelift/src/lib.rs#L366-L374
195+
//
196+
// Whether or not it is still applicable here is unsure, but it's left
197+
// the same as-is for now to reduce the likelihood of problems arising.
198+
ir::ArgumentExtension::Uext
199+
}
189200
}
190201

191202
/// Emit unwind info for an x86 target.

crates/cranelift/src/lib.rs

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -343,6 +343,7 @@ struct BuiltinFunctionSignatures {
343343

344344
host_call_conv: CallConv,
345345
wasm_call_conv: CallConv,
346+
argument_extension: ir::ArgumentExtension,
346347
}
347348

348349
impl BuiltinFunctionSignatures {
@@ -351,6 +352,7 @@ impl BuiltinFunctionSignatures {
351352
pointer_type: compiler.isa().pointer_type(),
352353
host_call_conv: CallConv::triple_default(compiler.isa().triple()),
353354
wasm_call_conv: wasm_call_conv(compiler.isa(), compiler.tunables()),
355+
argument_extension: compiler.isa().default_argument_extension(),
354356
}
355357
}
356358

@@ -363,16 +365,7 @@ impl BuiltinFunctionSignatures {
363365
}
364366

365367
fn i32(&self) -> AbiParam {
366-
// Some platform ABIs require i32 values to be zero- or sign-
367-
// extended to the full register width. We need to indicate
368-
// this here by using the appropriate .uext or .sext attribute.
369-
// The attribute can be added unconditionally; platforms whose
370-
// ABI does not require such extensions will simply ignore it.
371-
// Note that currently all i32 arguments or return values used
372-
// by builtin functions are unsigned, so we always use .uext.
373-
// If that ever changes, we will have to add a second type
374-
// marker here.
375-
AbiParam::new(ir::types::I32).uext()
368+
AbiParam::new(ir::types::I32)
376369
}
377370

378371
fn i64(&self) -> AbiParam {
@@ -418,6 +411,16 @@ impl BuiltinFunctionSignatures {
418411
fn host_signature(&self, builtin: BuiltinFunctionIndex) -> Signature {
419412
let mut sig = self.wasm_signature(builtin);
420413
sig.call_conv = self.host_call_conv;
414+
415+
// Once we're declaring the signature of a host function we must
416+
// respect the default ABI of the platform which is where argument
417+
// extension of params/results may come into play.
418+
for arg in sig.params.iter_mut().chain(sig.returns.iter_mut()) {
419+
if arg.value_type.is_int() {
420+
arg.extension = self.argument_extension;
421+
}
422+
}
423+
421424
sig
422425
}
423426
}

tests/disas/gc/drc/array-new-fixed.wat

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
;; gv1 = load.i64 notrap aligned readonly gv0+8
1515
;; gv2 = load.i64 notrap aligned gv1+16
1616
;; gv3 = vmctx
17-
;; sig0 = (i64 vmctx, i32 uext, i32 uext, i32 uext, i32 uext) -> i64 tail
17+
;; sig0 = (i64 vmctx, i32, i32, i32, i32) -> i64 tail
1818
;; fn0 = colocated u1:27 sig0
1919
;; stack_limit = gv2
2020
;;

tests/disas/gc/drc/array-new.wat

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
;; gv1 = load.i64 notrap aligned readonly gv0+8
1515
;; gv2 = load.i64 notrap aligned gv1+16
1616
;; gv3 = vmctx
17-
;; sig0 = (i64 vmctx, i32 uext, i32 uext, i32 uext, i32 uext) -> i64 tail
17+
;; sig0 = (i64 vmctx, i32, i32, i32, i32) -> i64 tail
1818
;; fn0 = colocated u1:27 sig0
1919
;; stack_limit = gv2
2020
;;

tests/disas/gc/drc/br-on-cast-fail.wat

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
;; gv1 = load.i64 notrap aligned readonly gv0+8
2323
;; gv2 = load.i64 notrap aligned gv1+16
2424
;; gv3 = vmctx
25-
;; sig0 = (i64 vmctx, i32 uext, i32 uext) -> i32 uext tail
25+
;; sig0 = (i64 vmctx, i32, i32) -> i32 tail
2626
;; sig1 = (i64 vmctx, i64) tail
2727
;; sig2 = (i64 vmctx, i64) tail
2828
;; fn0 = colocated u1:35 sig0

0 commit comments

Comments
 (0)