Skip to content

Better float casting tests in coretests#152597

Open
eggyal wants to merge 1 commit intorust-lang:mainfrom
eggyal:float-casting-coretests
Open

Better float casting tests in coretests#152597
eggyal wants to merge 1 commit intorust-lang:mainfrom
eggyal:float-casting-coretests

Conversation

@eggyal
Copy link
Contributor

@eggyal eggyal commented Feb 14, 2026

A direct port of the float casting tests from MIRI.

Closes #152592

r? tgross35

A direct port of the float casting tests from MIRI.
@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-libs Relevant to the library team, which will review and decide on the PR/issue. labels Feb 14, 2026
@rustbot
Copy link
Collaborator

rustbot commented Feb 14, 2026

tgross35 is currently at their maximum review capacity.
They may take a while to respond.

@rust-log-analyzer
Copy link
Collaborator

The job aarch64-gnu-llvm-20-2 failed! Check out the build log: (web) (plain enhanced) (plain)

Click to see the possible cause of the failure (guessed by this bot)
REPOSITORY                                   TAG       IMAGE ID       CREATED       SIZE
ghcr.io/dependabot/dependabot-updater-core   latest    afc745c7535d   2 weeks ago   783MB
=> Removing docker images...
Deleted Images:
untagged: ghcr.io/dependabot/dependabot-updater-core:latest
untagged: ghcr.io/dependabot/dependabot-updater-core@sha256:faae3d3a1dedd24cde388bb506bbacc0f7ed1eae99ebac129af66acd8540c84a
deleted: sha256:afc745c7535da1bb12f92c273b9a7e9c52c3f12c5873714b2542da259c6d9769
deleted: sha256:64e147d5e54d9be8b8aa322e511cda02296eda4b8b8d063c6a314833aca50e29
deleted: sha256:5cba409bb463f4e7fa1a19f695450170422582c1bc7c0e934d893b4e5f558bc6
deleted: sha256:cddc6ebd344b0111eaab170ead1dfda24acdfe865ed8a12599a34d338fa8e28b
deleted: sha256:2412c3f334d79134573cd45e657fb6cc0abd75bef3881458b0d498d936545c8d
---
[RUSTC-TIMING] corebenches test:true 9.150
[RUSTC-TIMING] allocbenches test:true 7.771
[RUSTC-TIMING] alloctests test:true 18.276
[RUSTC-TIMING] alloctests test:true 18.292
error: VerifierErrors([VerifierError { location: inst10, context: Some("v10 = select.i32 v8, v6, v5  ; v6 = -128"), message: "arg 2 (v5) has type i8, expected i32" }])

error: cranelift verify error:
       function u0:535(f128, i8, i64, i64) system_v {
           ss0 = explicit_slot 16, align = 8
           ss1 = explicit_slot 16, align = 8
           ss2 = explicit_slot 8, align = 8
           ss3 = explicit_slot 16, align = 8
           ss4 = explicit_slot 16, align = 8
           gv0 = symbol colocated userextname3
           gv1 = symbol colocated userextname5
           sig0 = (f128) -> i8 system_v
           sig1 = (f128, f128) -> i32 system_v
           sig2 = (i64 sret, i64) system_v
           sig3 = (i64, i64) -> i64, i64 system_v
           sig4 = (i8, i8, i64, i64, i64) system_v
           fn0 = u0:1272 sig0
           fn1 = u0:1054 sig1
           fn2 = u0:917 sig2
           fn3 = u0:1267 sig3
           fn4 = colocated u0:25 sig4
       
                                       block0(v0: f128, v1: i8, v2: i64, v3: i64):
                                           v4 -> v0
                                           v33 -> v1
                                           nop 
                                           stack_store v2, ss0
                                           stack_store v3, ss0+8
                                           jump block1
       
                                       block1:
                                           nop 
       @0000                               v5 = call fn0(v4)
       @0000                               v6 = iconst.i32 -128
       @0000                               v7 = iconst.i32 127
       @0000                               v8 = icmp_imm slt v5, -128
       @0000                               v9 = icmp_imm sgt v5, 127
       @0000                               v10 = select v8, v6, v5  ; v6 = -128
       ;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       ; error: inst10 (v10 = select.i32 v8, v6, v5  ; v6 = -128): arg 2 (v5) has type i8, expected i32
       
       @0000                               v11 = select v9, v7, v10  ; v7 = 127
       @0000                               v12 = ireduce.i8 v11
       @0000                               v13 = call fn1(v4, v4)
       @0000                               v14 = iconst.i32 0
       @0000                               v15 = icmp eq v13, v14  ; v14 = 0
       @0000                               v16 = iconst.i8 0
       @0000                               v17 = select v15, v12, v16  ; v16 = 0
                                           v32 -> v17
       @0001                               v18 = stack_addr.i64 ss0
       @0001                               stack_store v18, ss2
       @0001                               v19 = stack_load.i64 ss2
       @0001                               v20 = stack_addr.i64 ss4
       @0001                               call fn2(v20, v19)
       @0001                               jump block2
       
                                       block2:
       @0001                               nop 
       @0001                               v21 = iconst.i64 0
       @0001                               v22 = imul_imm v21, 16  ; v21 = 0
       @0001                               v23 = stack_addr.i64 ss3
       @0001                               v24 = iadd v23, v22
       @0001                               v25 = stack_addr.i64 ss4
       @0001                               v26 = load.i64 notrap aligned v25
       @0001                               v27 = load.i64 notrap aligned v25+8
       @0001                               store notrap aligned v26, v24
       @0001                               store notrap aligned v27, v24+8
       @0001                               v28 = symbol_value.i64 gv0
       @0001                               v29 = stack_addr.i64 ss3
       @0001                               v30, v31 = call fn3(v28, v29)
       @0001                               stack_store v30, ss1
       @0001                               stack_store v31, ss1+8
       @0001                               jump block3
       
                                       block3:
       @0001                               nop 
       @0002                               v34 = symbol_value.i64 gv1
       @0002                               v35 = stack_load.i64 ss1
       @0002                               v36 = stack_load.i64 ss1+8
       @0002                               call fn4(v32, v33, v35, v36, v34)
       @0002                               jump block4
       
                                       block4:
       @0002                               nop 
       @0003                               return
       }
       
       ; 1 verifier error detected (see above). Compilation aborted.
       

fn floats::casts::casts::assert_ftoi_unrep(_1: f128, _2: i8, _3: &str) -> () {
    debug f => _1;
    debug i => _2;
    debug msg => _3;
    let mut _0: ();
    let _4: ();
    let mut _5: i8;
    let mut _6: std::fmt::Arguments<'_>;
    let _7: (&&str,);
    let mut _8: &&str;
    let mut _10: core::fmt::rt::Argument<'_>;
    let mut _11: &[u8; 15];
    let _12: &[core::fmt::rt::Argument<'_>; 1];
    let mut _13: &&str;
    scope 1 {
        debug args => _7;
        let _9: [core::fmt::rt::Argument<'_>; 1];
        scope 2 {
            debug args => _9;
        }
    }

    bb0: {
        _5 = copy _1 as i8 (FloatToInt);
        _8 = &_3;
        _7 = (move _8,);
        _13 = copy (_7.0: &&str);
        _10 = core::fmt::rt::Argument::<'_>::new_display::<&str>(copy _13) -> [return: bb1, unwind unreachable];
    }

    bb1: {
        _9 = [move _10];
        _11 = const b"\x0cf128 -> i8: \xc0\x00";
        _12 = &_9;
        _6 = std::fmt::Arguments::<'_>::new::<15, 1>(move _11, copy _12) -> [return: bb2, unwind unreachable];
    }

    bb2: {
        _4 = floats::casts::assert_eq_msg::<i8, std::fmt::Arguments<'_>>(move _5, copy _2, move _6) -> [return: bb3, unwind unreachable];
    }

    bb3: {
        return;
    }
}

alloc45171 (size: 15, align: 1) {
    0c 66 31 32 38 20 2d 3e 20 69 38 3a 20 c0 00    │ .f128 -> i8: ..
}

error: VerifierErrors([VerifierError { location: inst7, context: Some("v6 = select.i32 v5, v4, v2  ; v4 = 255"), message: "arg 2 (v2) has type i8, expected i32" }])

error: cranelift verify error:
       function u0:773(f128) -> i8 system_v {
           sig0 = (f128) -> i8 system_v
           sig1 = (f128, f128) -> i32 system_v
           fn0 = u0:1968 sig0
           fn1 = u0:928 sig1
       
                                       block0(v0: f128):
                                           v1 -> v0
                                           nop 
                                           jump block1
       
                                       block1:
                                           nop 
       @0000                               v2 = call fn0(v1)
       @0000                               v3 = iconst.i32 0
       @0000                               v4 = iconst.i32 255
       @0000                               v5 = icmp_imm ugt v2, -1
       @0000                               v6 = select v5, v4, v2  ; v4 = 255
       ;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       ; error: inst7 (v6 = select.i32 v5, v4, v2  ; v4 = 255): arg 2 (v2) has type i8, expected i32
       
       @0000                               v7 = ireduce.i8 v6
       @0000                               v8 = call fn1(v1, v1)
       @0000                               v9 = iconst.i32 0
       @0000                               v10 = icmp eq v8, v9  ; v9 = 0
       @0000                               v11 = iconst.i8 0
       @0000                               v12 = select v10, v7, v11  ; v11 = 0
                                           v13 -> v12
       @0000                               jump block2
       
                                       block2:
       @0000                               nop 
       @0001                               return v13
       }
       
       ; 1 verifier error detected (see above). Compilation aborted.
       

fn <f128 as std::convert::FloatToInt<u8>>::to_int_unchecked(_1: f128) -> u8 {
    debug self => _1;
    let mut _0: u8;

    bb0: {
        _0 = std::intrinsics::float_to_int_unchecked::<f128, u8>(move _1) -> [return: bb1, unwind unreachable];
    }

    bb1: {
        return;
    }
}

[RUSTC-TIMING] coretests test:true 65.662
error: could not compile `coretests` (test "coretests") due to 4 previous errors
env -u RUSTC_WRAPPER CARGO_ENCODED_RUSTDOCFLAGS="-Csymbol-mangling-version=v0\u{1f}-Zannotate-moves\u{1f}-Zrandomize-layout\u{1f}-Zunstable-options\u{1f}--check-cfg=cfg(bootstrap)\u{1f}-Wrustdoc::invalid_codeblock_attributes\u{1f}--crate-version\u{1f}1.95.0-nightly\t(deee2f05e\t2026-02-14)" CARGO_ENCODED_RUSTFLAGS="-Csymbol-mangling-version=v0\u{1f}-Zannotate-moves\u{1f}-Zrandomize-layout\u{1f}-Zunstable-options\u{1f}--check-cfg=cfg(bootstrap)\u{1f}-Zmacro-backtrace\u{1f}-Csplit-debuginfo=off\u{1f}-Clink-arg=-L/usr/lib/llvm-20/lib\u{1f}-Cllvm-args=-import-instr-limit=10\u{1f}-Clink-args=-Wl,-z,origin\u{1f}-Clink-args=-Wl,-rpath,$ORIGIN/../lib\u{1f}--cap-lints=allow\u{1f}--cfg\u{1f}randomized_layouts" RUSTC="/checkout/obj/build/aarch64-unknown-linux-gnu/stage2-codegen/cg_clif/dist/rustc-clif" RUSTDOC="/checkout/obj/build/aarch64-unknown-linux-gnu/stage2-codegen/cg_clif/dist/rustdoc-clif" "/checkout/obj/build/aarch64-unknown-linux-gnu/stage0/bin/cargo" "test" "--manifest-path" "/checkout/obj/build/aarch64-unknown-linux-gnu/stage2-codegen/cg_clif/build/sysroot_tests/Cargo.toml" "--target-dir" "/checkout/obj/build/aarch64-unknown-linux-gnu/stage2-codegen/cg_clif/build/sysroot_tests_target" "--locked" "--target" "aarch64-unknown-linux-gnu" "-p" "coretests" "-p" "alloctests" "--tests" "--" "-q" exited with status ExitStatus(unix_wait_status(25856))
Command `/checkout/obj/build/aarch64-unknown-linux-gnu/stage0/bin/cargo run -Zwarnings --target aarch64-unknown-linux-gnu -Zbinary-dep-depinfo -j 4 -Zroot-dir=/checkout --locked --color=always --profile=release --manifest-path /checkout/compiler/rustc_codegen_cranelift/build_system/Cargo.toml -- test --download-dir /checkout/obj/build/cg_clif_download --out-dir /checkout/obj/build/aarch64-unknown-linux-gnu/stage2-codegen/cg_clif --no-unstable-features --use-backend cranelift --sysroot llvm --skip-test testsuite.extended_sysroot [workdir=/checkout/compiler/rustc_codegen_cranelift]` failed with exit code 1
Created at: src/bootstrap/src/core/build_steps/test.rs:3877:25
Executed at: src/bootstrap/src/core/build_steps/test.rs:3922:26

Command has failed. Rerun with -v to see more details.
Bootstrap failed while executing `--stage 2 test --skip tests --skip coverage-map --skip coverage-run --skip library --skip tidyselftest`
Build completed unsuccessfully in 0:25:37
  local time: Sat Feb 14 01:07:00 UTC 2026
  network time: Sat, 14 Feb 2026 01:07:00 GMT
##[error]Process completed with exit code 1.

@okaneco
Copy link
Contributor

okaneco commented Feb 14, 2026

My first exposure to the cranelift codebase was in the float constant PR, so I'm by no means an expert.

There was a change in that PR that you might want to cherry pick so it solves the separate f128->int casts issue c4582c8

For this CI failure, in the lib_call on line 220, should that to_ty be replaced with ret_ty in the third argument of the Vec? to_ty would still be an I8 if passed directly, but line 208 sets ret_ty to an I32.

} else if from_ty == types::F128 && to_ty.is_int() {
let ret_ty = if to_ty.bits() < 32 { types::I32 } else { to_ty };
let name = format!(
"__fix{sign}tf{size}i",
sign = if from_signed { "" } else { "un" },
size = match ret_ty {
types::I32 => 's',
types::I64 => 'd',
types::I128 => 't',
_ => unreachable!("{from_ty:?}"),
},
);
let ret =
fx.lib_call(&name, vec![AbiParam::new(from_ty)], vec![AbiParam::new(to_ty)], &[from])
[0];
let val = if ret_ty == to_ty {
ret
} else {
let (min, max) = match (to_ty, to_signed) {
(types::I8, false) => (0, i64::from(u8::MAX)),
(types::I16, false) => (0, i64::from(u16::MAX)),
(types::I8, true) => (i64::from(i8::MIN as u32), i64::from(i8::MAX as u32)),
(types::I16, true) => (i64::from(i16::MIN as u32), i64::from(i16::MAX as u32)),
_ => unreachable!("{to_ty:?}"),
};
let min_val = fx.bcx.ins().iconst(types::I32, min);
let max_val = fx.bcx.ins().iconst(types::I32, max);
let val = if to_signed {
let has_underflow = fx.bcx.ins().icmp_imm(IntCC::SignedLessThan, ret, min);
let has_overflow = fx.bcx.ins().icmp_imm(IntCC::SignedGreaterThan, ret, max);
let bottom_capped = fx.bcx.ins().select(has_underflow, min_val, ret);
fx.bcx.ins().select(has_overflow, max_val, bottom_capped)
} else {
let has_overflow = fx.bcx.ins().icmp_imm(IntCC::UnsignedGreaterThan, ret, max);
fx.bcx.ins().select(has_overflow, max_val, ret)
};
fx.bcx.ins().ireduce(to_ty, val)
};
if let Some(false) = fx.tcx.sess.opts.unstable_opts.saturating_float_casts {
return val;
}
let is_not_nan = fcmp(fx, FloatCC::Equal, from, from);
let zero = type_zero_value(&mut fx.bcx, to_ty);
fx.bcx.ins().select(is_not_nan, val, zero)
} else {

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-libs Relevant to the library team, which will review and decide on the PR/issue.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Better float casting tests are needed in coretests

5 participants