Set signext
or zeroext
for integer arguments on RISC-V
This commit is contained in:
parent
03df13b70d
commit
6b65524620
@ -732,6 +732,7 @@ pub fn adjust_for_rust_abi<C>(&mut self, cx: &C, abi: SpecAbi)
|
|||||||
let spec = cx.target_spec();
|
let spec = cx.target_spec();
|
||||||
match &spec.arch[..] {
|
match &spec.arch[..] {
|
||||||
"x86" => x86::compute_rust_abi_info(cx, self, abi),
|
"x86" => x86::compute_rust_abi_info(cx, self, abi),
|
||||||
|
"riscv32" | "riscv64" => riscv::compute_rust_abi_info(cx, self, abi),
|
||||||
_ => {}
|
_ => {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
use crate::abi::call::{ArgAbi, ArgExtension, CastTarget, FnAbi, PassMode, Reg, RegKind, Uniform};
|
use crate::abi::call::{ArgAbi, ArgExtension, CastTarget, FnAbi, PassMode, Reg, RegKind, Uniform};
|
||||||
use crate::abi::{self, Abi, FieldsShape, HasDataLayout, Size, TyAbiInterface, TyAndLayout};
|
use crate::abi::{self, Abi, FieldsShape, HasDataLayout, Size, TyAbiInterface, TyAndLayout};
|
||||||
use crate::spec::HasTargetSpec;
|
use crate::spec::HasTargetSpec;
|
||||||
|
use crate::spec::abi::Abi as SpecAbi;
|
||||||
|
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
enum RegPassKind {
|
enum RegPassKind {
|
||||||
@ -365,3 +366,29 @@ pub(crate) fn compute_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>)
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn compute_rust_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>, abi: SpecAbi)
|
||||||
|
where
|
||||||
|
Ty: TyAbiInterface<'a, C> + Copy,
|
||||||
|
C: HasDataLayout + HasTargetSpec,
|
||||||
|
{
|
||||||
|
if abi == SpecAbi::RustIntrinsic {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let xlen = cx.data_layout().pointer_size.bits();
|
||||||
|
|
||||||
|
for arg in fn_abi.args.iter_mut() {
|
||||||
|
if arg.is_ignore() {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// LLVM integers types do not differentiate between signed or unsigned integers.
|
||||||
|
// Some RISC-V instructions do not have a `.w` suffix version, they use all the
|
||||||
|
// XLEN bits. By explicitly setting the `signext` or `zeroext` attribute
|
||||||
|
// according to signedness to avoid unnecessary integer extending instructions.
|
||||||
|
//
|
||||||
|
// See https://github.com/rust-lang/rust/issues/114508 for details.
|
||||||
|
extend_integer_width(arg, xlen);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
96
tests/assembly/rust-abi-arg-attr.rs
Normal file
96
tests/assembly/rust-abi-arg-attr.rs
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
//@ assembly-output: emit-asm
|
||||||
|
//@ revisions: riscv64 riscv64-zbb
|
||||||
|
//@ compile-flags: -C opt-level=3
|
||||||
|
//@ [riscv64] compile-flags: --target riscv64gc-unknown-linux-gnu
|
||||||
|
//@ [riscv64] needs-llvm-components: riscv
|
||||||
|
//@ [riscv64-zbb] compile-flags: --target riscv64gc-unknown-linux-gnu
|
||||||
|
//@ [riscv64-zbb] compile-flags: -C target-feature=+zbb
|
||||||
|
//@ [riscv64-zbb] needs-llvm-components: riscv
|
||||||
|
|
||||||
|
#![feature(no_core, lang_items, intrinsics, rustc_attrs)]
|
||||||
|
#![crate_type = "lib"]
|
||||||
|
#![no_std]
|
||||||
|
#![no_core]
|
||||||
|
|
||||||
|
// FIXME: Migrate these code after PR #130693 is landed.
|
||||||
|
// vvvvv core
|
||||||
|
|
||||||
|
#[lang = "sized"]
|
||||||
|
trait Sized {}
|
||||||
|
|
||||||
|
#[lang = "copy"]
|
||||||
|
trait Copy {}
|
||||||
|
|
||||||
|
impl Copy for i8 {}
|
||||||
|
impl Copy for u32 {}
|
||||||
|
impl Copy for i32 {}
|
||||||
|
|
||||||
|
#[lang = "neg"]
|
||||||
|
trait Neg {
|
||||||
|
type Output;
|
||||||
|
|
||||||
|
fn neg(self) -> Self::Output;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Neg for i8 {
|
||||||
|
type Output = i8;
|
||||||
|
|
||||||
|
fn neg(self) -> Self::Output {
|
||||||
|
-self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[lang = "Ordering"]
|
||||||
|
#[repr(i8)]
|
||||||
|
enum Ordering {
|
||||||
|
Less = -1,
|
||||||
|
Equal = 0,
|
||||||
|
Greater = 1,
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "rust-intrinsic" {
|
||||||
|
#[rustc_safe_intrinsic]
|
||||||
|
fn three_way_compare<T: Copy>(lhs: T, rhs: T) -> Ordering;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ^^^^^ core
|
||||||
|
|
||||||
|
// Reimplementation of function `{integer}::max`.
|
||||||
|
macro_rules! max {
|
||||||
|
($a:expr, $b:expr) => {
|
||||||
|
match three_way_compare($a, $b) {
|
||||||
|
Ordering::Less | Ordering::Equal => $b,
|
||||||
|
Ordering::Greater => $a,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
// CHECK-LABEL: issue_114508_u32:
|
||||||
|
pub fn issue_114508_u32(a: u32, b: u32) -> u32 {
|
||||||
|
// CHECK-NEXT: .cfi_startproc
|
||||||
|
|
||||||
|
// riscv64-NEXT: bltu a1, a0, .[[RET:.+]]
|
||||||
|
// riscv64-NEXT: mv a0, a1
|
||||||
|
// riscv64-NEXT: .[[RET]]:
|
||||||
|
|
||||||
|
// riscv64-zbb-NEXT: maxu a0, a0, a1
|
||||||
|
|
||||||
|
// CHECK-NEXT: ret
|
||||||
|
max!(a, b)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
// CHECK-LABEL: issue_114508_i32:
|
||||||
|
pub fn issue_114508_i32(a: i32, b: i32) -> i32 {
|
||||||
|
// CHECK-NEXT: .cfi_startproc
|
||||||
|
|
||||||
|
// riscv64-NEXT: blt a1, a0, .[[RET:.+]]
|
||||||
|
// riscv64-NEXT: mv a0, a1
|
||||||
|
// riscv64-NEXT: .[[RET]]:
|
||||||
|
|
||||||
|
// riscv64-zbb-NEXT: max a0, a0, a1
|
||||||
|
|
||||||
|
// CHECK-NEXT: ret
|
||||||
|
max!(a, b)
|
||||||
|
}
|
@ -5,7 +5,7 @@
|
|||||||
// Ensure that when val < base, we do not divide or multiply.
|
// Ensure that when val < base, we do not divide or multiply.
|
||||||
|
|
||||||
// CHECK-LABEL: @checked_ilog
|
// CHECK-LABEL: @checked_ilog
|
||||||
// CHECK-SAME: (i16 noundef %val, i16 noundef %base)
|
// CHECK-SAME: (i16{{.*}} %val, i16{{.*}} %base)
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub fn checked_ilog(val: u16, base: u16) -> Option<u32> {
|
pub fn checked_ilog(val: u16, base: u16) -> Option<u32> {
|
||||||
// CHECK-NOT: udiv
|
// CHECK-NOT: udiv
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
// Thanks to poison semantics, this doesn't even need branches.
|
// Thanks to poison semantics, this doesn't even need branches.
|
||||||
|
|
||||||
// CHECK-LABEL: @checked_sub_unsigned
|
// CHECK-LABEL: @checked_sub_unsigned
|
||||||
// CHECK-SAME: (i16 noundef %a, i16 noundef %b)
|
// CHECK-SAME: (i16{{.*}} %a, i16{{.*}} %b)
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub fn checked_sub_unsigned(a: u16, b: u16) -> Option<u16> {
|
pub fn checked_sub_unsigned(a: u16, b: u16) -> Option<u16> {
|
||||||
// CHECK-DAG: %[[IS_SOME:.+]] = icmp uge i16 %a, %b
|
// CHECK-DAG: %[[IS_SOME:.+]] = icmp uge i16 %a, %b
|
||||||
@ -26,7 +26,7 @@ pub fn checked_sub_unsigned(a: u16, b: u16) -> Option<u16> {
|
|||||||
// looking for no-wrap flags, we just need there to not be any masking.
|
// looking for no-wrap flags, we just need there to not be any masking.
|
||||||
|
|
||||||
// CHECK-LABEL: @checked_shl_unsigned
|
// CHECK-LABEL: @checked_shl_unsigned
|
||||||
// CHECK-SAME: (i32 noundef %a, i32 noundef %b)
|
// CHECK-SAME: (i32{{.*}} %a, i32{{.*}} %b)
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub fn checked_shl_unsigned(a: u32, b: u32) -> Option<u32> {
|
pub fn checked_shl_unsigned(a: u32, b: u32) -> Option<u32> {
|
||||||
// CHECK-DAG: %[[IS_SOME:.+]] = icmp ult i32 %b, 32
|
// CHECK-DAG: %[[IS_SOME:.+]] = icmp ult i32 %b, 32
|
||||||
@ -41,7 +41,7 @@ pub fn checked_shl_unsigned(a: u32, b: u32) -> Option<u32> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// CHECK-LABEL: @checked_shr_unsigned
|
// CHECK-LABEL: @checked_shr_unsigned
|
||||||
// CHECK-SAME: (i32 noundef %a, i32 noundef %b)
|
// CHECK-SAME: (i32{{.*}} %a, i32{{.*}} %b)
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub fn checked_shr_unsigned(a: u32, b: u32) -> Option<u32> {
|
pub fn checked_shr_unsigned(a: u32, b: u32) -> Option<u32> {
|
||||||
// CHECK-DAG: %[[IS_SOME:.+]] = icmp ult i32 %b, 32
|
// CHECK-DAG: %[[IS_SOME:.+]] = icmp ult i32 %b, 32
|
||||||
@ -56,7 +56,7 @@ pub fn checked_shr_unsigned(a: u32, b: u32) -> Option<u32> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// CHECK-LABEL: @checked_shl_signed
|
// CHECK-LABEL: @checked_shl_signed
|
||||||
// CHECK-SAME: (i32 noundef %a, i32 noundef %b)
|
// CHECK-SAME: (i32{{.*}} %a, i32{{.*}} %b)
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub fn checked_shl_signed(a: i32, b: u32) -> Option<i32> {
|
pub fn checked_shl_signed(a: i32, b: u32) -> Option<i32> {
|
||||||
// CHECK-DAG: %[[IS_SOME:.+]] = icmp ult i32 %b, 32
|
// CHECK-DAG: %[[IS_SOME:.+]] = icmp ult i32 %b, 32
|
||||||
@ -71,7 +71,7 @@ pub fn checked_shl_signed(a: i32, b: u32) -> Option<i32> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// CHECK-LABEL: @checked_shr_signed
|
// CHECK-LABEL: @checked_shr_signed
|
||||||
// CHECK-SAME: (i32 noundef %a, i32 noundef %b)
|
// CHECK-SAME: (i32{{.*}} %a, i32{{.*}} %b)
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub fn checked_shr_signed(a: i32, b: u32) -> Option<i32> {
|
pub fn checked_shr_signed(a: i32, b: u32) -> Option<i32> {
|
||||||
// CHECK-DAG: %[[IS_SOME:.+]] = icmp ult i32 %b, 32
|
// CHECK-DAG: %[[IS_SOME:.+]] = icmp ult i32 %b, 32
|
||||||
@ -86,7 +86,7 @@ pub fn checked_shr_signed(a: i32, b: u32) -> Option<i32> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// CHECK-LABEL: @checked_add_one_unwrap_unsigned
|
// CHECK-LABEL: @checked_add_one_unwrap_unsigned
|
||||||
// CHECK-SAME: (i32 noundef %x)
|
// CHECK-SAME: (i32{{.*}} %x)
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub fn checked_add_one_unwrap_unsigned(x: u32) -> u32 {
|
pub fn checked_add_one_unwrap_unsigned(x: u32) -> u32 {
|
||||||
// CHECK: %[[IS_MAX:.+]] = icmp eq i32 %x, -1
|
// CHECK: %[[IS_MAX:.+]] = icmp eq i32 %x, -1
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
pub struct Foo(u16);
|
pub struct Foo(u16);
|
||||||
|
|
||||||
// CHECK-LABEL: @check_lt
|
// CHECK-LABEL: @check_lt
|
||||||
// CHECK-SAME: (i16 noundef %[[A:.+]], i16 noundef %[[B:.+]])
|
// CHECK-SAME: (i16{{.*}} %[[A:.+]], i16{{.*}} %[[B:.+]])
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub fn check_lt(a: Foo, b: Foo) -> bool {
|
pub fn check_lt(a: Foo, b: Foo) -> bool {
|
||||||
// CHECK: %[[R:.+]] = icmp ult i16 %[[A]], %[[B]]
|
// CHECK: %[[R:.+]] = icmp ult i16 %[[A]], %[[B]]
|
||||||
@ -21,7 +21,7 @@ pub fn check_lt(a: Foo, b: Foo) -> bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// CHECK-LABEL: @check_le
|
// CHECK-LABEL: @check_le
|
||||||
// CHECK-SAME: (i16 noundef %[[A:.+]], i16 noundef %[[B:.+]])
|
// CHECK-SAME: (i16{{.*}} %[[A:.+]], i16{{.*}} %[[B:.+]])
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub fn check_le(a: Foo, b: Foo) -> bool {
|
pub fn check_le(a: Foo, b: Foo) -> bool {
|
||||||
// CHECK: %[[R:.+]] = icmp ule i16 %[[A]], %[[B]]
|
// CHECK: %[[R:.+]] = icmp ule i16 %[[A]], %[[B]]
|
||||||
@ -30,7 +30,7 @@ pub fn check_le(a: Foo, b: Foo) -> bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// CHECK-LABEL: @check_gt
|
// CHECK-LABEL: @check_gt
|
||||||
// CHECK-SAME: (i16 noundef %[[A:.+]], i16 noundef %[[B:.+]])
|
// CHECK-SAME: (i16{{.*}} %[[A:.+]], i16{{.*}} %[[B:.+]])
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub fn check_gt(a: Foo, b: Foo) -> bool {
|
pub fn check_gt(a: Foo, b: Foo) -> bool {
|
||||||
// CHECK: %[[R:.+]] = icmp ugt i16 %[[A]], %[[B]]
|
// CHECK: %[[R:.+]] = icmp ugt i16 %[[A]], %[[B]]
|
||||||
@ -39,7 +39,7 @@ pub fn check_gt(a: Foo, b: Foo) -> bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// CHECK-LABEL: @check_ge
|
// CHECK-LABEL: @check_ge
|
||||||
// CHECK-SAME: (i16 noundef %[[A:.+]], i16 noundef %[[B:.+]])
|
// CHECK-SAME: (i16{{.*}} %[[A:.+]], i16{{.*}} %[[B:.+]])
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub fn check_ge(a: Foo, b: Foo) -> bool {
|
pub fn check_ge(a: Foo, b: Foo) -> bool {
|
||||||
// CHECK: %[[R:.+]] = icmp uge i16 %[[A]], %[[B]]
|
// CHECK: %[[R:.+]] = icmp uge i16 %[[A]], %[[B]]
|
||||||
|
@ -6,11 +6,11 @@
|
|||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub fn sum(x: u32, y: u32) -> u32 {
|
pub fn sum(x: u32, y: u32) -> u32 {
|
||||||
// YES-LABEL: define{{.*}}i32 @sum(i32 noundef %0, i32 noundef %1)
|
// YES-LABEL: define{{.*}}i32 @sum(i32{{.*}} %0, i32{{.*}} %1)
|
||||||
// YES-NEXT: %3 = add i32 %1, %0
|
// YES-NEXT: %3 = add i32 %1, %0
|
||||||
// YES-NEXT: ret i32 %3
|
// YES-NEXT: ret i32 %3
|
||||||
|
|
||||||
// NO-LABEL: define{{.*}}i32 @sum(i32 noundef %x, i32 noundef %y)
|
// NO-LABEL: define{{.*}}i32 @sum(i32{{.*}} %x, i32{{.*}} %y)
|
||||||
// NO-NEXT: start:
|
// NO-NEXT: start:
|
||||||
// NO-NEXT: %z = add i32 %y, %x
|
// NO-NEXT: %z = add i32 %y, %x
|
||||||
// NO-NEXT: ret i32 %z
|
// NO-NEXT: ret i32 %z
|
||||||
|
@ -32,7 +32,7 @@ pub fn boolean(x: bool) -> bool {
|
|||||||
x
|
x
|
||||||
}
|
}
|
||||||
|
|
||||||
// CHECK: i8 @maybeuninit_boolean(i8 %x)
|
// CHECK: i8 @maybeuninit_boolean(i8{{.*}} %x)
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub fn maybeuninit_boolean(x: MaybeUninit<bool>) -> MaybeUninit<bool> {
|
pub fn maybeuninit_boolean(x: MaybeUninit<bool>) -> MaybeUninit<bool> {
|
||||||
x
|
x
|
||||||
@ -44,19 +44,19 @@ pub fn enum_bool(x: MyBool) -> MyBool {
|
|||||||
x
|
x
|
||||||
}
|
}
|
||||||
|
|
||||||
// CHECK: i8 @maybeuninit_enum_bool(i8 %x)
|
// CHECK: i8 @maybeuninit_enum_bool(i8{{.*}} %x)
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub fn maybeuninit_enum_bool(x: MaybeUninit<MyBool>) -> MaybeUninit<MyBool> {
|
pub fn maybeuninit_enum_bool(x: MaybeUninit<MyBool>) -> MaybeUninit<MyBool> {
|
||||||
x
|
x
|
||||||
}
|
}
|
||||||
|
|
||||||
// CHECK: noundef{{( range\(i32 0, 1114112\))?}} i32 @char(i32 noundef{{( range\(i32 0, 1114112\))?}} %x)
|
// CHECK: noundef{{( range\(i32 0, 1114112\))?}} i32 @char(i32{{.*}}{{( range\(i32 0, 1114112\))?}} %x)
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub fn char(x: char) -> char {
|
pub fn char(x: char) -> char {
|
||||||
x
|
x
|
||||||
}
|
}
|
||||||
|
|
||||||
// CHECK: i32 @maybeuninit_char(i32 %x)
|
// CHECK: i32 @maybeuninit_char(i32{{.*}} %x)
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub fn maybeuninit_char(x: MaybeUninit<char>) -> MaybeUninit<char> {
|
pub fn maybeuninit_char(x: MaybeUninit<char>) -> MaybeUninit<char> {
|
||||||
x
|
x
|
||||||
|
@ -10,8 +10,7 @@
|
|||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
// CHECK-LABEL: @signed_cmp
|
// CHECK-LABEL: @signed_cmp
|
||||||
// DEBUG-SAME: (i16 %a, i16 %b)
|
// CHECK-SAME: (i16{{.*}} %a, i16{{.*}} %b)
|
||||||
// OPTIM-SAME: (i16 noundef %a, i16 noundef %b)
|
|
||||||
pub fn signed_cmp(a: i16, b: i16) -> std::cmp::Ordering {
|
pub fn signed_cmp(a: i16, b: i16) -> std::cmp::Ordering {
|
||||||
// DEBUG: %[[GT:.+]] = icmp sgt i16 %a, %b
|
// DEBUG: %[[GT:.+]] = icmp sgt i16 %a, %b
|
||||||
// DEBUG: %[[ZGT:.+]] = zext i1 %[[GT]] to i8
|
// DEBUG: %[[ZGT:.+]] = zext i1 %[[GT]] to i8
|
||||||
@ -29,8 +28,7 @@ pub fn signed_cmp(a: i16, b: i16) -> std::cmp::Ordering {
|
|||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
// CHECK-LABEL: @unsigned_cmp
|
// CHECK-LABEL: @unsigned_cmp
|
||||||
// DEBUG-SAME: (i16 %a, i16 %b)
|
// CHECK-SAME: (i16{{.*}} %a, i16{{.*}} %b)
|
||||||
// OPTIM-SAME: (i16 noundef %a, i16 noundef %b)
|
|
||||||
pub fn unsigned_cmp(a: u16, b: u16) -> std::cmp::Ordering {
|
pub fn unsigned_cmp(a: u16, b: u16) -> std::cmp::Ordering {
|
||||||
// DEBUG: %[[GT:.+]] = icmp ugt i16 %a, %b
|
// DEBUG: %[[GT:.+]] = icmp ugt i16 %a, %b
|
||||||
// DEBUG: %[[ZGT:.+]] = zext i1 %[[GT]] to i8
|
// DEBUG: %[[ZGT:.+]] = zext i1 %[[GT]] to i8
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
#[repr(transparent)]
|
#[repr(transparent)]
|
||||||
pub struct Transparent32(u32);
|
pub struct Transparent32(u32);
|
||||||
|
|
||||||
// CHECK: i32 @make_transparent(i32 noundef %x)
|
// CHECK: i32 @make_transparent(i32{{.*}} %x)
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub fn make_transparent(x: u32) -> Transparent32 {
|
pub fn make_transparent(x: u32) -> Transparent32 {
|
||||||
// CHECK-NOT: alloca
|
// CHECK-NOT: alloca
|
||||||
@ -18,7 +18,7 @@ pub fn make_transparent(x: u32) -> Transparent32 {
|
|||||||
a
|
a
|
||||||
}
|
}
|
||||||
|
|
||||||
// CHECK: i32 @make_closure(i32 noundef %x)
|
// CHECK: i32 @make_closure(i32{{.*}} %x)
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub fn make_closure(x: i32) -> impl Fn(i32) -> i32 {
|
pub fn make_closure(x: i32) -> impl Fn(i32) -> i32 {
|
||||||
// CHECK-NOT: alloca
|
// CHECK-NOT: alloca
|
||||||
@ -40,7 +40,7 @@ pub fn make_transparent_pair(x: (u16, u16)) -> TransparentPair {
|
|||||||
a
|
a
|
||||||
}
|
}
|
||||||
|
|
||||||
// CHECK-LABEL: { i32, i32 } @make_2_tuple(i32 noundef %x)
|
// CHECK-LABEL: { i32, i32 } @make_2_tuple(i32{{.*}} %x)
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub fn make_2_tuple(x: u32) -> (u32, u32) {
|
pub fn make_2_tuple(x: u32) -> (u32, u32) {
|
||||||
// CHECK-NOT: alloca
|
// CHECK-NOT: alloca
|
||||||
@ -59,7 +59,7 @@ pub fn make_cell_of_bool(b: bool) -> std::cell::Cell<bool> {
|
|||||||
std::cell::Cell::new(b)
|
std::cell::Cell::new(b)
|
||||||
}
|
}
|
||||||
|
|
||||||
// CHECK-LABEL: { i8, i16 } @make_cell_of_bool_and_short(i1 noundef zeroext %b, i16 noundef %s)
|
// CHECK-LABEL: { i8, i16 } @make_cell_of_bool_and_short(i1 noundef zeroext %b, i16{{.*}} %s)
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub fn make_cell_of_bool_and_short(b: bool, s: u16) -> std::cell::Cell<(bool, u16)> {
|
pub fn make_cell_of_bool_and_short(b: bool, s: u16) -> std::cell::Cell<(bool, u16)> {
|
||||||
// CHECK-NOT: alloca
|
// CHECK-NOT: alloca
|
||||||
@ -92,7 +92,7 @@ pub fn make_struct_0() -> Struct0 {
|
|||||||
|
|
||||||
pub struct Struct1(i32);
|
pub struct Struct1(i32);
|
||||||
|
|
||||||
// CHECK-LABEL: i32 @make_struct_1(i32 noundef %a)
|
// CHECK-LABEL: i32 @make_struct_1(i32{{.*}} %a)
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub fn make_struct_1(a: i32) -> Struct1 {
|
pub fn make_struct_1(a: i32) -> Struct1 {
|
||||||
// CHECK: ret i32 %a
|
// CHECK: ret i32 %a
|
||||||
@ -104,7 +104,7 @@ pub fn make_struct_1(a: i32) -> Struct1 {
|
|||||||
|
|
||||||
// bit32-LABEL: void @make_struct_2_asc({{.*}} sret({{[^,]*}}) {{.*}} %s,
|
// bit32-LABEL: void @make_struct_2_asc({{.*}} sret({{[^,]*}}) {{.*}} %s,
|
||||||
// bit64-LABEL: { i64, i16 } @make_struct_2_asc(
|
// bit64-LABEL: { i64, i16 } @make_struct_2_asc(
|
||||||
// CHECK-SAME: i16 noundef %a, i64 noundef %b)
|
// CHECK-SAME: i16{{.*}} %a, i64 noundef %b)
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub fn make_struct_2_asc(a: i16, b: i64) -> Struct2Asc {
|
pub fn make_struct_2_asc(a: i16, b: i64) -> Struct2Asc {
|
||||||
// CHECK-NOT: alloca
|
// CHECK-NOT: alloca
|
||||||
@ -122,7 +122,7 @@ pub fn make_struct_2_asc(a: i16, b: i64) -> Struct2Asc {
|
|||||||
|
|
||||||
// bit32-LABEL: void @make_struct_2_desc({{.*}} sret({{[^,]*}}) {{.*}} %s,
|
// bit32-LABEL: void @make_struct_2_desc({{.*}} sret({{[^,]*}}) {{.*}} %s,
|
||||||
// bit64-LABEL: { i64, i16 } @make_struct_2_desc(
|
// bit64-LABEL: { i64, i16 } @make_struct_2_desc(
|
||||||
// CHECK-SAME: i64 noundef %a, i16 noundef %b)
|
// CHECK-SAME: i64 noundef %a, i16{{.*}} %b)
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub fn make_struct_2_desc(a: i64, b: i16) -> Struct2Desc {
|
pub fn make_struct_2_desc(a: i64, b: i16) -> Struct2Desc {
|
||||||
// CHECK-NOT: alloca
|
// CHECK-NOT: alloca
|
||||||
|
@ -24,7 +24,7 @@ pub fn nonzero_int(x: NonZero<u128>) -> NonZero<u128> {
|
|||||||
x
|
x
|
||||||
}
|
}
|
||||||
|
|
||||||
// CHECK: noundef range(i8 0, 3) i8 @optional_bool(i8 noundef range(i8 0, 3) %x)
|
// CHECK: noundef range(i8 0, 3) i8 @optional_bool(i8{{.*}} range(i8 0, 3) %x)
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub fn optional_bool(x: Option<bool>) -> Option<bool> {
|
pub fn optional_bool(x: Option<bool>) -> Option<bool> {
|
||||||
x
|
x
|
||||||
@ -36,7 +36,7 @@ pub enum Enum0 {
|
|||||||
C,
|
C,
|
||||||
}
|
}
|
||||||
|
|
||||||
// CHECK: noundef range(i8 0, 4) i8 @enum0_value(i8 noundef range(i8 0, 4) %x)
|
// CHECK: noundef range(i8 0, 4) i8 @enum0_value(i8{{.*}} range(i8 0, 4) %x)
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub fn enum0_value(x: Enum0) -> Enum0 {
|
pub fn enum0_value(x: Enum0) -> Enum0 {
|
||||||
x
|
x
|
||||||
|
93
tests/codegen/rust-abi-arch-specific-adjustment.rs
Normal file
93
tests/codegen/rust-abi-arch-specific-adjustment.rs
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
//@ compile-flags: -O -C no-prepopulate-passes
|
||||||
|
//@ revisions: riscv64
|
||||||
|
|
||||||
|
//@[riscv64] only-riscv64
|
||||||
|
//@[riscv64] compile-flags: --target riscv64gc-unknown-linux-gnu
|
||||||
|
//@[riscv64] needs-llvm-components: riscv
|
||||||
|
|
||||||
|
#![crate_type = "lib"]
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
// riscv64: define noundef i8 @arg_attr_u8(i8 noundef zeroext %x)
|
||||||
|
pub fn arg_attr_u8(x: u8) -> u8 {
|
||||||
|
x
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
// riscv64: define noundef i16 @arg_attr_u16(i16 noundef zeroext %x)
|
||||||
|
pub fn arg_attr_u16(x: u16) -> u16 {
|
||||||
|
x
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
// riscv64: define noundef i32 @arg_attr_u32(i32 noundef signext %x)
|
||||||
|
pub fn arg_attr_u32(x: u32) -> u32 {
|
||||||
|
x
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
// riscv64: define noundef i64 @arg_attr_u64(i64 noundef %x)
|
||||||
|
pub fn arg_attr_u64(x: u64) -> u64 {
|
||||||
|
x
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
// riscv64: define noundef i128 @arg_attr_u128(i128 noundef %x)
|
||||||
|
pub fn arg_attr_u128(x: u128) -> u128 {
|
||||||
|
x
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
// riscv64: define noundef i8 @arg_attr_i8(i8 noundef signext %x)
|
||||||
|
pub fn arg_attr_i8(x: i8) -> i8 {
|
||||||
|
x
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
// riscv64: define noundef i16 @arg_attr_i16(i16 noundef signext %x)
|
||||||
|
pub fn arg_attr_i16(x: i16) -> i16 {
|
||||||
|
x
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
// riscv64: define noundef i32 @arg_attr_i32(i32 noundef signext %x)
|
||||||
|
pub fn arg_attr_i32(x: i32) -> i32 {
|
||||||
|
x
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
// riscv64: define noundef i64 @arg_attr_i64(i64 noundef %x)
|
||||||
|
pub fn arg_attr_i64(x: i64) -> i64 {
|
||||||
|
x
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
// riscv64: define noundef i128 @arg_attr_i128(i128 noundef %x)
|
||||||
|
pub fn arg_attr_i128(x: i128) -> i128 {
|
||||||
|
x
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
// riscv64: define noundef zeroext i1 @arg_attr_bool(i1 noundef zeroext %x)
|
||||||
|
pub fn arg_attr_bool(x: bool) -> bool {
|
||||||
|
x
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
// ignore-tidy-linelength
|
||||||
|
// riscv64: define noundef{{( range\(i32 0, 1114112\))?}} i32 @arg_attr_char(i32 noundef signext{{( range\(i32 0, 1114112\))?}} %x)
|
||||||
|
pub fn arg_attr_char(x: char) -> char {
|
||||||
|
x
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
// riscv64: define noundef float @arg_attr_f32(float noundef %x)
|
||||||
|
pub fn arg_attr_f32(x: f32) -> f32 {
|
||||||
|
x
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
// riscv64: define noundef double @arg_attr_f64(double noundef %x)
|
||||||
|
pub fn arg_attr_f64(x: f64) -> f64 {
|
||||||
|
x
|
||||||
|
}
|
@ -25,7 +25,7 @@ pub fn bool_to_byte(b: bool) -> u8 {
|
|||||||
unsafe { std::mem::transmute(b) }
|
unsafe { std::mem::transmute(b) }
|
||||||
}
|
}
|
||||||
|
|
||||||
// CHECK-LABEL: define{{.*}}zeroext i1 @byte_to_bool(i8 %byte)
|
// CHECK-LABEL: define{{.*}}zeroext i1 @byte_to_bool(i8{{.*}} %byte)
|
||||||
// CHECK: %_0 = trunc i8 %byte to i1
|
// CHECK: %_0 = trunc i8 %byte to i1
|
||||||
// CHECK-NEXT: ret i1 %_0
|
// CHECK-NEXT: ret i1 %_0
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
|
@ -131,7 +131,7 @@ pub fn test_CUnionU128(_: CUnionU128) {
|
|||||||
pub union UnionBool {
|
pub union UnionBool {
|
||||||
b: bool,
|
b: bool,
|
||||||
}
|
}
|
||||||
// CHECK: define {{(dso_local )?}}noundef zeroext i1 @test_UnionBool(i8 %b)
|
// CHECK: define {{(dso_local )?}}noundef zeroext i1 @test_UnionBool(i8{{.*}} %b)
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub fn test_UnionBool(b: UnionBool) -> bool {
|
pub fn test_UnionBool(b: UnionBool) -> bool {
|
||||||
unsafe { b.b }
|
unsafe { b.b }
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
#![crate_type = "lib"]
|
#![crate_type = "lib"]
|
||||||
|
|
||||||
// CHECK-LABEL: define{{.*}}i32 @test(i32 noundef %a, i32 noundef %b)
|
// CHECK-LABEL: define{{.*}}i32 @test(i32{{.*}} %a, i32{{.*}} %b)
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub fn test(a: u32, b: u32) -> u32 {
|
pub fn test(a: u32, b: u32) -> u32 {
|
||||||
let c = a + b;
|
let c = a + b;
|
||||||
|
Loading…
Reference in New Issue
Block a user