diff --git a/cranelift/filetests/isa/riscv/abi.cton b/cranelift/filetests/isa/riscv/abi.cton index bb27ac20ae..0282e94874 100644 --- a/cranelift/filetests/isa/riscv/abi.cton +++ b/cranelift/filetests/isa/riscv/abi.cton @@ -41,6 +41,13 @@ ebb0(v0: i64): return v0 } +function int_ext(i8, i8 sext, i8 uext) -> i8 { +ebb0(v1: i8, v2: i8, v3: i8): +; check: $ebb0($v1: i8, $(v2x=$VX): i32, $(v3x=$VX): i32): +; check: ireduce.i8 $v2x +; check: ireduce.i8 $v3x +} + function vector_split_args(i64x4) -> i64 { ebb0(v0: i64x4): ; check: $ebb0($(v0al=$VX): i32, $(v0ah=$VX): i32, $(v0bl=$VX): i32, $(v0bh=$VX): i32, $(v0cl=$VX): i32, $(v0ch=$VX): i32, $(v0dl=$VX): i32, $(v0dh=$VX): i32): diff --git a/lib/cretonne/src/isa/riscv/abi.rs b/lib/cretonne/src/isa/riscv/abi.rs index 7813a59cef..9d78abc007 100644 --- a/lib/cretonne/src/isa/riscv/abi.rs +++ b/lib/cretonne/src/isa/riscv/abi.rs @@ -6,13 +6,14 @@ //! This doesn't support the soft-float ABI at the moment. use abi::{ArgAction, ValueConversion, ArgAssigner, legalize_args}; -use ir::{Signature, ArgumentType, ArgumentLoc}; +use ir::{Signature, Type, ArgumentType, ArgumentLoc, ArgumentExtension}; use isa::riscv::registers::{GPR, FPR}; use settings as shared_settings; struct Args { pointer_bits: u16, pointer_bytes: u32, + pointer_type: Type, regs: u32, offset: u32, } @@ -22,6 +23,7 @@ impl Args { Args { pointer_bits: bits, pointer_bytes: bits as u32 / 8, + pointer_type: Type::int(bits).unwrap(), regs: 0, offset: 0, } @@ -50,6 +52,19 @@ impl ArgAssigner for Args { return ArgAction::Convert(ValueConversion::IntSplit); } + // Small integers are extended to the size of a pointer register. + if ty.is_int() && ty.bits() < self.pointer_bits { + match arg.extension { + ArgumentExtension::None => {} + ArgumentExtension::Uext => { + return ArgAction::Convert(ValueConversion::Uext(self.pointer_type)) + } + ArgumentExtension::Sext => { + return ArgAction::Convert(ValueConversion::Sext(self.pointer_type)) + } + } + } + if self.regs < 8 { // Assign to a register. let reg = if ty.is_float() {