From be2369708a0fd53fc1ed80cbcca25f24e12a781d Mon Sep 17 00:00:00 2001 From: spore Date: Wed, 8 Jan 2025 18:31:29 +0800 Subject: [PATCH 01/10] Detect overflow when the literal is larger than i128::MAX --- compiler/rustc_lint/src/types/literal.rs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_lint/src/types/literal.rs b/compiler/rustc_lint/src/types/literal.rs index 83942918e3b58..c3e558a3e20a9 100644 --- a/compiler/rustc_lint/src/types/literal.rs +++ b/compiler/rustc_lint/src/types/literal.rs @@ -206,12 +206,15 @@ fn get_type_suggestion(t: Ty<'_>, val: u128, negative: bool) -> Option<&'static ty::Uint(_) => Some(Integer::fit_unsigned(val).uint_ty_str()), ty::Int(_) if negative => Some(Integer::fit_signed(-(val as i128)).int_ty_str()), ty::Int(int) => { - let signed = Integer::fit_signed(val as i128); let unsigned = Integer::fit_unsigned(val); - Some(if Some(unsigned.size().bits()) == int.bit_width() { - unsigned.uint_ty_str() + Some(if let Ok(signed) = i128::try_from(val).map(Integer::fit_signed) { + if Some(unsigned.size().bits()) == int.bit_width() { + unsigned.uint_ty_str() + } else { + signed.int_ty_str() + } } else { - signed.int_ty_str() + unsigned.uint_ty_str() }) } _ => None, From 330be171440eb4efe479c5b1fcfd079153c5159d Mon Sep 17 00:00:00 2001 From: spore Date: Wed, 8 Jan 2025 19:00:10 +0800 Subject: [PATCH 02/10] Detect overflow when the literal is negative --- compiler/rustc_lint/src/types/literal.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_lint/src/types/literal.rs b/compiler/rustc_lint/src/types/literal.rs index c3e558a3e20a9..13eca89fba67b 100644 --- a/compiler/rustc_lint/src/types/literal.rs +++ b/compiler/rustc_lint/src/types/literal.rs @@ -204,7 +204,13 @@ fn get_type_suggestion(t: Ty<'_>, val: u128, negative: bool) -> Option<&'static match t.kind() { ty::Uint(ty::UintTy::Usize) | ty::Int(ty::IntTy::Isize) => None, ty::Uint(_) => Some(Integer::fit_unsigned(val).uint_ty_str()), - ty::Int(_) if negative => Some(Integer::fit_signed(-(val as i128)).int_ty_str()), + ty::Int(_) if negative => { + if val > i128::MAX as u128 + 1 { + None + } else { + Some(Integer::fit_signed(val.wrapping_neg() as i128).int_ty_str()) + } + } ty::Int(int) => { let unsigned = Integer::fit_unsigned(val); Some(if let Ok(signed) = i128::try_from(val).map(Integer::fit_signed) { From 1517a41c57b328b2e89641d79b1272e7004f7514 Mon Sep 17 00:00:00 2001 From: spore Date: Wed, 8 Jan 2025 19:00:35 +0800 Subject: [PATCH 03/10] Add test cases and test for `HELP` --- tests/ui/lint/type-overflow.rs | 26 +++++++++++++++ tests/ui/lint/type-overflow.stderr | 51 ++++++++++++++++++++++++++---- 2 files changed, 70 insertions(+), 7 deletions(-) diff --git a/tests/ui/lint/type-overflow.rs b/tests/ui/lint/type-overflow.rs index 7239e1c983764..0848d676e237c 100644 --- a/tests/ui/lint/type-overflow.rs +++ b/tests/ui/lint/type-overflow.rs @@ -3,20 +3,46 @@ fn main() { let error = 255i8; //~WARNING literal out of range for `i8` + //~^ HELP consider using the type `u8` instead let ok = 0b1000_0001; // should be ok -> i32 let ok = 0b0111_1111i8; // should be ok -> 127i8 let fail = 0b1000_0001i8; //~WARNING literal out of range for `i8` + //~^ HELP consider using the type `u8` instead + //~| HELP consider using the type `u8` for the literal and cast it to `i8` let fail = 0x8000_0000_0000_0000i64; //~WARNING literal out of range for `i64` + //~^ HELP consider using the type `u64` instead + //~| HELP consider using the type `u64` for the literal and cast it to `i64` let fail = 0x1_FFFF_FFFFu32; //~WARNING literal out of range for `u32` + //~^ HELP consider using the type `u64` instead let fail: i128 = 0x8000_0000_0000_0000_0000_0000_0000_0000; //~^ WARNING literal out of range for `i128` + //~| HELP consider using the type `u128` instead + //~| HELP consider using the type `u128` for the literal and cast it to `i128` + + let fail = 0x8000_0000_0000_0000_0000_0000_0000_0000; + //~^ WARNING literal out of range for `i32` + //~| HELP consider using the type `u128` instead + + let fail = -0x8000_0000_0000_0000_0000_0000_0000_0000; + //~^ WARNING literal out of range for `i32` + //~| HELP consider using the type `i128` instead + + let fail = -0x8000_0000_0000_0000_0000_0000_0000_0001i128; + //~^ WARNING literal out of range for `i128` + + let fail = 340282366920938463463374607431768211455i8; + //~^ WARNING literal out of range for `i8` + //~| HELP consider using the type `u128` instead let fail = 0x8FFF_FFFF_FFFF_FFFE; //~WARNING literal out of range for `i32` + //~| HELP consider using the type `i128` instead + //~| HELP let fail = -0b1111_1111i8; //~WARNING literal out of range for `i8` + //~| HELP consider using the type `i16` instead } diff --git a/tests/ui/lint/type-overflow.stderr b/tests/ui/lint/type-overflow.stderr index e7c90dcc81bb2..dbbe81e5c182d 100644 --- a/tests/ui/lint/type-overflow.stderr +++ b/tests/ui/lint/type-overflow.stderr @@ -13,7 +13,7 @@ LL | #![warn(overflowing_literals)] | ^^^^^^^^^^^^^^^^^^^^ warning: literal out of range for `i8` - --> $DIR/type-overflow.rs:10:16 + --> $DIR/type-overflow.rs:11:16 | LL | let fail = 0b1000_0001i8; | ^^^^^^^^^^^^^ @@ -29,7 +29,7 @@ LL | let fail = 0b1000_0001u8 as i8; | ~~~~~~~~~~~~~~~~~~~ warning: literal out of range for `i64` - --> $DIR/type-overflow.rs:12:16 + --> $DIR/type-overflow.rs:15:16 | LL | let fail = 0x8000_0000_0000_0000i64; | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -45,7 +45,7 @@ LL | let fail = 0x8000_0000_0000_0000u64 as i64; | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ warning: literal out of range for `u32` - --> $DIR/type-overflow.rs:14:16 + --> $DIR/type-overflow.rs:19:16 | LL | let fail = 0x1_FFFF_FFFFu32; | ^^^^^^^^^^^^^^^^ help: consider using the type `u64` instead: `0x1_FFFF_FFFFu64` @@ -53,7 +53,7 @@ LL | let fail = 0x1_FFFF_FFFFu32; = note: the literal `0x1_FFFF_FFFFu32` (decimal `8589934591`) does not fit into the type `u32` and will become `4294967295u32` warning: literal out of range for `i128` - --> $DIR/type-overflow.rs:16:22 + --> $DIR/type-overflow.rs:22:22 | LL | let fail: i128 = 0x8000_0000_0000_0000_0000_0000_0000_0000; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -66,7 +66,44 @@ LL | let fail: i128 = 0x8000_0000_0000_0000_0000_0000_0000_0000u128 as i128; | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ warning: literal out of range for `i32` - --> $DIR/type-overflow.rs:19:16 + --> $DIR/type-overflow.rs:27:16 + | +LL | let fail = 0x8000_0000_0000_0000_0000_0000_0000_0000; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the literal `0x8000_0000_0000_0000_0000_0000_0000_0000` (decimal `170141183460469231731687303715884105728`) does not fit into the type `i32` and will become `0i32` + = help: consider using the type `u128` instead + +warning: literal out of range for `i32` + --> $DIR/type-overflow.rs:31:17 + | +LL | let fail = -0x8000_0000_0000_0000_0000_0000_0000_0000; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the literal `0x8000_0000_0000_0000_0000_0000_0000_0000` (decimal `170141183460469231731687303715884105728`) does not fit into the type `i32` + = note: and the value `-0x8000_0000_0000_0000_0000_0000_0000_0000` will become `0i32` + = help: consider using the type `i128` instead + +warning: literal out of range for `i128` + --> $DIR/type-overflow.rs:35:17 + | +LL | let fail = -0x8000_0000_0000_0000_0000_0000_0000_0001i128; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the literal `0x8000_0000_0000_0000_0000_0000_0000_0001i128` (decimal `170141183460469231731687303715884105729`) does not fit into the type `i128` + = note: and the value `-0x8000_0000_0000_0000_0000_0000_0000_0001i128` will become `170141183460469231731687303715884105727i128` + +warning: literal out of range for `i8` + --> $DIR/type-overflow.rs:38:16 + | +LL | let fail = 340282366920938463463374607431768211455i8; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the literal `340282366920938463463374607431768211455i8` does not fit into the type `i8` whose range is `-128..=127` + = help: consider using the type `u128` instead + +warning: literal out of range for `i32` + --> $DIR/type-overflow.rs:42:16 | LL | let fail = 0x8FFF_FFFF_FFFF_FFFE; | ^^^^^^^^^^^^^^^^^^^^^ @@ -79,7 +116,7 @@ LL | let fail = 0x8FFF_FFFF_FFFF_FFFEu32 as i32; | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ warning: literal out of range for `i8` - --> $DIR/type-overflow.rs:21:17 + --> $DIR/type-overflow.rs:46:17 | LL | let fail = -0b1111_1111i8; | ^^^^^^^^^^^^^ help: consider using the type `i16` instead: `0b1111_1111i16` @@ -87,5 +124,5 @@ LL | let fail = -0b1111_1111i8; = note: the literal `0b1111_1111i8` (decimal `255`) does not fit into the type `i8` = note: and the value `-0b1111_1111i8` will become `1i8` -warning: 7 warnings emitted +warning: 11 warnings emitted From c04e65dbc5f936fdd4dc53ba7b7a058165aad157 Mon Sep 17 00:00:00 2001 From: spore Date: Thu, 9 Jan 2025 02:02:40 +0800 Subject: [PATCH 04/10] Extract integer conversion into a function --- compiler/rustc_lint/src/types/literal.rs | 38 ++++++++++++++---------- 1 file changed, 22 insertions(+), 16 deletions(-) diff --git a/compiler/rustc_lint/src/types/literal.rs b/compiler/rustc_lint/src/types/literal.rs index 13eca89fba67b..4faf345bcd58f 100644 --- a/compiler/rustc_lint/src/types/literal.rs +++ b/compiler/rustc_lint/src/types/literal.rs @@ -204,29 +204,35 @@ fn get_type_suggestion(t: Ty<'_>, val: u128, negative: bool) -> Option<&'static match t.kind() { ty::Uint(ty::UintTy::Usize) | ty::Int(ty::IntTy::Isize) => None, ty::Uint(_) => Some(Integer::fit_unsigned(val).uint_ty_str()), - ty::Int(_) if negative => { - if val > i128::MAX as u128 + 1 { - None - } else { - Some(Integer::fit_signed(val.wrapping_neg() as i128).int_ty_str()) - } - } ty::Int(int) => { - let unsigned = Integer::fit_unsigned(val); - Some(if let Ok(signed) = i128::try_from(val).map(Integer::fit_signed) { - if Some(unsigned.size().bits()) == int.bit_width() { - unsigned.uint_ty_str() - } else { - signed.int_ty_str() - } + let signed = literal_to_i128(val, negative).map(|v| Integer::fit_signed(v)); + if negative { + signed.map(Integer::int_ty_str) } else { - unsigned.uint_ty_str() - }) + let unsigned = Integer::fit_unsigned(val); + Some(if let Some(signed) = signed { + if Some(unsigned.size().bits()) == int.bit_width() { + unsigned.uint_ty_str() + } else { + signed.int_ty_str() + } + } else { + unsigned.uint_ty_str() + }) + } } _ => None, } } +fn literal_to_i128(val: u128, negative: bool) -> Option { + if negative { + (val <= i128::MAX as u128 + 1).then(|| val.wrapping_neg() as i128) + } else { + val.try_into().ok() + } +} + fn lint_int_literal<'tcx>( cx: &LateContext<'tcx>, type_limits: &TypeLimits, From 4a857557563a06a70c1c7533cf4220f42b37198a Mon Sep 17 00:00:00 2001 From: spore Date: Sat, 11 Jan 2025 13:05:15 +0800 Subject: [PATCH 05/10] Minor simplification Apply eta-reduction on map to simplify code and make the style more consistent --- compiler/rustc_lint/src/types/literal.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_lint/src/types/literal.rs b/compiler/rustc_lint/src/types/literal.rs index 4faf345bcd58f..f7a59437bbc27 100644 --- a/compiler/rustc_lint/src/types/literal.rs +++ b/compiler/rustc_lint/src/types/literal.rs @@ -205,7 +205,7 @@ fn get_type_suggestion(t: Ty<'_>, val: u128, negative: bool) -> Option<&'static ty::Uint(ty::UintTy::Usize) | ty::Int(ty::IntTy::Isize) => None, ty::Uint(_) => Some(Integer::fit_unsigned(val).uint_ty_str()), ty::Int(int) => { - let signed = literal_to_i128(val, negative).map(|v| Integer::fit_signed(v)); + let signed = literal_to_i128(val, negative).map(Integer::fit_signed); if negative { signed.map(Integer::int_ty_str) } else { From f52724c917216a8c9126479b0e0c097afe447593 Mon Sep 17 00:00:00 2001 From: spore Date: Sun, 12 Jan 2025 19:50:01 +0800 Subject: [PATCH 06/10] Add comment on case to mark the original issue --- tests/ui/lint/type-overflow.rs | 2 +- tests/ui/lint/type-overflow.stderr | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/ui/lint/type-overflow.rs b/tests/ui/lint/type-overflow.rs index 0848d676e237c..102d042773b99 100644 --- a/tests/ui/lint/type-overflow.rs +++ b/tests/ui/lint/type-overflow.rs @@ -28,7 +28,7 @@ fn main() { //~^ WARNING literal out of range for `i32` //~| HELP consider using the type `u128` instead - let fail = -0x8000_0000_0000_0000_0000_0000_0000_0000; + let fail = -0x8000_0000_0000_0000_0000_0000_0000_0000; // issue #131849 //~^ WARNING literal out of range for `i32` //~| HELP consider using the type `i128` instead diff --git a/tests/ui/lint/type-overflow.stderr b/tests/ui/lint/type-overflow.stderr index dbbe81e5c182d..720044c68ebda 100644 --- a/tests/ui/lint/type-overflow.stderr +++ b/tests/ui/lint/type-overflow.stderr @@ -77,7 +77,7 @@ LL | let fail = 0x8000_0000_0000_0000_0000_0000_0000_0000; warning: literal out of range for `i32` --> $DIR/type-overflow.rs:31:17 | -LL | let fail = -0x8000_0000_0000_0000_0000_0000_0000_0000; +LL | let fail = -0x8000_0000_0000_0000_0000_0000_0000_0000; // issue #131849 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: the literal `0x8000_0000_0000_0000_0000_0000_0000_0000` (decimal `170141183460469231731687303715884105728`) does not fit into the type `i32` From 74e2e8b59834aede7aafee57e00ede07ae13739b Mon Sep 17 00:00:00 2001 From: spore Date: Sun, 12 Jan 2025 20:18:53 +0800 Subject: [PATCH 07/10] Suggest the smallest fitting type instead Changes the behavior of the `overflowing_literals` suggestion so that it always suggest the smallest type regardless of the original type size. --- compiler/rustc_lint/src/types/literal.rs | 4 ++-- tests/ui/lint/type-overflow.rs | 2 +- tests/ui/lint/type-overflow.stderr | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_lint/src/types/literal.rs b/compiler/rustc_lint/src/types/literal.rs index f7a59437bbc27..4b5163522f866 100644 --- a/compiler/rustc_lint/src/types/literal.rs +++ b/compiler/rustc_lint/src/types/literal.rs @@ -204,14 +204,14 @@ fn get_type_suggestion(t: Ty<'_>, val: u128, negative: bool) -> Option<&'static match t.kind() { ty::Uint(ty::UintTy::Usize) | ty::Int(ty::IntTy::Isize) => None, ty::Uint(_) => Some(Integer::fit_unsigned(val).uint_ty_str()), - ty::Int(int) => { + ty::Int(_) => { let signed = literal_to_i128(val, negative).map(Integer::fit_signed); if negative { signed.map(Integer::int_ty_str) } else { let unsigned = Integer::fit_unsigned(val); Some(if let Some(signed) = signed { - if Some(unsigned.size().bits()) == int.bit_width() { + if unsigned.size() < signed.size() { unsigned.uint_ty_str() } else { signed.int_ty_str() diff --git a/tests/ui/lint/type-overflow.rs b/tests/ui/lint/type-overflow.rs index 102d042773b99..1e74a8925f621 100644 --- a/tests/ui/lint/type-overflow.rs +++ b/tests/ui/lint/type-overflow.rs @@ -40,7 +40,7 @@ fn main() { //~| HELP consider using the type `u128` instead let fail = 0x8FFF_FFFF_FFFF_FFFE; //~WARNING literal out of range for `i32` - //~| HELP consider using the type `i128` instead + //~| HELP consider using the type `u64` instead //~| HELP let fail = -0b1111_1111i8; //~WARNING literal out of range for `i8` diff --git a/tests/ui/lint/type-overflow.stderr b/tests/ui/lint/type-overflow.stderr index 720044c68ebda..9fdb05ed1c036 100644 --- a/tests/ui/lint/type-overflow.stderr +++ b/tests/ui/lint/type-overflow.stderr @@ -109,7 +109,7 @@ LL | let fail = 0x8FFF_FFFF_FFFF_FFFE; | ^^^^^^^^^^^^^^^^^^^^^ | = note: the literal `0x8FFF_FFFF_FFFF_FFFE` (decimal `10376293541461622782`) does not fit into the type `i32` and will become `-2i32` - = help: consider using the type `i128` instead + = help: consider using the type `u64` instead help: to use as a negative number (decimal `-2`), consider using the type `u32` for the literal and cast it to `i32` | LL | let fail = 0x8FFF_FFFF_FFFF_FFFEu32 as i32; From c4a5e12567a4f5b540141c31c87f479bb3e73e63 Mon Sep 17 00:00:00 2001 From: Aeon <165953379+AeonSolstice@users.noreply.github.com> Date: Wed, 15 Jan 2025 16:08:22 -0500 Subject: [PATCH 08/10] Clarify note in `std::sync::LazyLock` example --- library/std/src/sync/lazy_lock.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/std/src/sync/lazy_lock.rs b/library/std/src/sync/lazy_lock.rs index 1e4f9b79e0f4a..98c83d8d326ca 100644 --- a/library/std/src/sync/lazy_lock.rs +++ b/library/std/src/sync/lazy_lock.rs @@ -31,7 +31,7 @@ union Data { /// ``` /// use std::sync::LazyLock; /// -/// // n.b. static items do not call [`Drop`] on program termination, so this won't be deallocated. +/// // Note: static items do not call [`Drop`] on program termination, so this won't be deallocated. /// // this is fine, as the OS can deallocate the terminated program faster than we can free memory /// // but tools like valgrind might report "memory leaks" as it isn't obvious this is intentional. /// static DEEP_THOUGHT: LazyLock = LazyLock::new(|| { From fef3dd4354148e875b4ceb521748773217d39fd9 Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Wed, 15 Jan 2025 15:15:52 +0100 Subject: [PATCH 09/10] use indirect return for `i128` and `f128` on wasm32 --- compiler/rustc_target/src/callconv/wasm.rs | 12 ++++++ tests/codegen/f128-wasm32-callconv.rs | 49 ++++++++++++++++++++++ tests/codegen/i128-wasm32-callconv.rs | 49 ++++++++++++++++++++++ 3 files changed, 110 insertions(+) create mode 100644 tests/codegen/f128-wasm32-callconv.rs create mode 100644 tests/codegen/i128-wasm32-callconv.rs diff --git a/compiler/rustc_target/src/callconv/wasm.rs b/compiler/rustc_target/src/callconv/wasm.rs index 3c4cd76a75464..d01b59cbb032b 100644 --- a/compiler/rustc_target/src/callconv/wasm.rs +++ b/compiler/rustc_target/src/callconv/wasm.rs @@ -1,3 +1,5 @@ +use rustc_abi::{BackendRepr, Float, Integer, Primitive}; + use crate::abi::call::{ArgAbi, FnAbi}; use crate::abi::{HasDataLayout, TyAbiInterface}; @@ -27,6 +29,16 @@ where if ret.layout.is_aggregate() && !unwrap_trivial_aggregate(cx, ret) { ret.make_indirect(); } + + // `long double`, `__int128_t` and `__uint128_t` use an indirect return + if let BackendRepr::Scalar(scalar) = ret.layout.backend_repr { + match scalar.primitive() { + Primitive::Int(Integer::I128, _) | Primitive::Float(Float::F128) => { + ret.make_indirect(); + } + _ => {} + } + } } fn classify_arg<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>) diff --git a/tests/codegen/f128-wasm32-callconv.rs b/tests/codegen/f128-wasm32-callconv.rs new file mode 100644 index 0000000000000..55adffd4db3ba --- /dev/null +++ b/tests/codegen/f128-wasm32-callconv.rs @@ -0,0 +1,49 @@ +//! Verify that Rust implements the expected calling convention for `f128` + +//@ add-core-stubs +//@ compile-flags: --target wasm32-wasip1 +//@ needs-llvm-components: webassembly + +#![crate_type = "lib"] +#![no_std] +#![no_core] +#![feature(no_core, lang_items, f128)] + +extern crate minicore; + +extern "C" { + fn extern_call(arg0: f128); + fn extern_ret() -> f128; +} + +#[no_mangle] +pub extern "C" fn pass(_arg0: u32, arg1: f128) { + // CHECK-LABEL: @pass( + // an f128 is passed via registers + // CHECK-SAME: fp128 noundef %arg1 + // CHECK: call void @extern_call + unsafe { extern_call(arg1) }; +} + +// Check that we produce the correct return ABI +#[no_mangle] +pub extern "C" fn ret(_arg0: u32, arg1: f128) -> f128 { + // CHECK-LABEL: @ret( + // but an f128 is returned via the stack + // CHECK-SAME: sret + // CHECK: store fp128 %arg1 + // CHECK-NEXT: ret void + arg1 +} + +// Check that we consume the correct return ABI +#[no_mangle] +pub extern "C" fn forward(dst: *mut f128) { + // CHECK-LABEL: @forward + // CHECK-SAME: ptr{{.*}} %dst) + // without optimizatons, an intermediate alloca is used + // CHECK: call void @extern_ret + // CHECK: store fp128 + // CHECK: ret void + unsafe { *dst = extern_ret() }; +} diff --git a/tests/codegen/i128-wasm32-callconv.rs b/tests/codegen/i128-wasm32-callconv.rs new file mode 100644 index 0000000000000..3dece56a9bb73 --- /dev/null +++ b/tests/codegen/i128-wasm32-callconv.rs @@ -0,0 +1,49 @@ +//! Verify that Rust implements the expected calling convention for `i128`/`u128`. + +//@ add-core-stubs +//@ compile-flags: --target wasm32-wasip1 +//@ needs-llvm-components: webassembly + +#![crate_type = "lib"] +#![no_std] +#![no_core] +#![feature(no_core, lang_items)] + +extern crate minicore; + +extern "C" { + fn extern_call(arg0: i128); + fn extern_ret() -> i128; +} + +#[no_mangle] +pub extern "C" fn pass(_arg0: u32, arg1: i128) { + // CHECK-LABEL: @pass( + // an i128 is passed via registers + // CHECK-SAME: i128 noundef %arg1 + // CHECK: call void @extern_call + unsafe { extern_call(arg1) }; +} + +// Check that we produce the correct return ABI +#[no_mangle] +pub extern "C" fn ret(_arg0: u32, arg1: i128) -> i128 { + // CHECK-LABEL: @ret( + // but an i128 is returned via the stack + // CHECK-SAME: sret + // CHECK: store i128 %arg1 + // CHECK-NEXT: ret void + arg1 +} + +// Check that we consume the correct return ABI +#[no_mangle] +pub extern "C" fn forward(dst: *mut i128) { + // CHECK-LABEL: @forward + // CHECK-SAME: ptr{{.*}} %dst) + // without optimizatons, an intermediate alloca is used + // CHECK: call void @extern_ret + // CHECK: store i128 + // CHECK: ret void + unsafe { *dst = extern_ret() }; +} From bbeb5e314ef2f3fd15aea4fe3e849e48a5b1d47f Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Thu, 16 Jan 2025 01:47:15 +0000 Subject: [PATCH 10/10] Update `compiler-builtins` to 0.1.144 The change between 0.1.143 and 0.1.144 includes refactoring that was in compiler-builtins before, but had to be reverted before landing in rust-lang/rust because the traits were leaking into diagnostics [1]. Recently a fix for this issue was merged [2] so the cleanup is reapplied here. This also acts as a regression test for [2]. [1]: https://github.com/rust-lang/rust/pull/128691#issuecomment-2272297610 [2]: https://github.com/rust-lang/rust/pull/135278 --- ...029-stdlib-Disable-f16-and-f128-in-compiler-builtins.patch | 4 ++-- library/Cargo.lock | 4 ++-- library/alloc/Cargo.toml | 2 +- library/std/Cargo.toml | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_codegen_cranelift/patches/0029-stdlib-Disable-f16-and-f128-in-compiler-builtins.patch b/compiler/rustc_codegen_cranelift/patches/0029-stdlib-Disable-f16-and-f128-in-compiler-builtins.patch index bf58e48515855..82dd5dcada7f0 100644 --- a/compiler/rustc_codegen_cranelift/patches/0029-stdlib-Disable-f16-and-f128-in-compiler-builtins.patch +++ b/compiler/rustc_codegen_cranelift/patches/0029-stdlib-Disable-f16-and-f128-in-compiler-builtins.patch @@ -16,8 +16,8 @@ index 7165c3e48af..968552ad435 100644 [dependencies] core = { path = "../core" } --compiler_builtins = { version = "=0.1.143", features = ['rustc-dep-of-std'] } -+compiler_builtins = { version = "=0.1.143", features = ['rustc-dep-of-std', 'no-f16-f128'] } +-compiler_builtins = { version = "=0.1.144", features = ['rustc-dep-of-std'] } ++compiler_builtins = { version = "=0.1.144", features = ['rustc-dep-of-std', 'no-f16-f128'] } [dev-dependencies] rand = { version = "0.8.5", default-features = false, features = ["alloc"] } diff --git a/library/Cargo.lock b/library/Cargo.lock index c8007dd9be046..13da832c53d8c 100644 --- a/library/Cargo.lock +++ b/library/Cargo.lock @@ -61,9 +61,9 @@ dependencies = [ [[package]] name = "compiler_builtins" -version = "0.1.143" +version = "0.1.144" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c85ba2077e3eab3dd81be4ece6b7fb2ad0887c1fb813e9a45400baf75c6c7c29" +checksum = "d18a7b7b5a56aa131e62314b4d862c9f6aa2860f615f3770094ec9064d7ec572" dependencies = [ "cc", "rustc-std-workspace-core", diff --git a/library/alloc/Cargo.toml b/library/alloc/Cargo.toml index 96caac890a35c..edb0aa4df3c1f 100644 --- a/library/alloc/Cargo.toml +++ b/library/alloc/Cargo.toml @@ -10,7 +10,7 @@ edition = "2021" [dependencies] core = { path = "../core" } -compiler_builtins = { version = "=0.1.143", features = ['rustc-dep-of-std'] } +compiler_builtins = { version = "=0.1.144", features = ['rustc-dep-of-std'] } [dev-dependencies] rand = { version = "0.8.5", default-features = false, features = ["alloc"] } diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml index da58d7c13bd12..0a4fd9f4c7123 100644 --- a/library/std/Cargo.toml +++ b/library/std/Cargo.toml @@ -17,7 +17,7 @@ cfg-if = { version = "1.0", features = ['rustc-dep-of-std'] } panic_unwind = { path = "../panic_unwind", optional = true } panic_abort = { path = "../panic_abort" } core = { path = "../core", public = true } -compiler_builtins = { version = "=0.1.143" } +compiler_builtins = { version = "=0.1.144" } unwind = { path = "../unwind" } hashbrown = { version = "0.15", default-features = false, features = [ 'rustc-dep-of-std',