rust-lang / rustc_codegen_cranelift

Cranelift based backend for rustc
Apache License 2.0
1.59k stars 100 forks source link

Arithmetic miscompilation #1460

Closed cbeuw closed 7 months ago

cbeuw commented 7 months ago

Fuzzer generated custom MIR:

#![feature(custom_mir, core_intrinsics)]
extern crate core;
use core::intrinsics::mir::*;

fn p(x: u8) {
    println!("{x}");
}

#[custom_mir(dialect = "runtime", phase = "initial")]
pub fn fn0() -> isize {
    mir! {
    let _3: isize;
    let _5: u8;
    let _8: i128;
    let _10: isize;
    let _22: ();
    {
    RET = 16_isize;
    _3 = RET * RET;
    Call(_5 = fn1(), ReturnTo(bb8), UnwindUnreachable())
    }
    bb8 = {
    _8 = _5 as i128;
    _10 = _8 as isize;
    RET = _3 * _10;
    _5 = RET as u8;
    Call(_22 = p(_5), ReturnTo(bb18), UnwindUnreachable())
    }
    bb18 = {
    Return()
    }

    }
}

pub fn fn1() -> u8 {
    42
}

pub fn main() {
    fn0();
}

After RET = _3 * _10, the value of RET should be 10752_isize (0x2A00). Casting to u8 is 0, so the program should print 0. This is what LLVM backend and Miri prints.

However, with rustc_codegen_cranelift at -Copt-level=3 it prints 42

$ dist/rustc-clif -Zmir-opt-level=0 -Copt-level=3 688739-debug.rs && ./688739-debug
42
rustc 1.78.0-nightly (3246e7951 2024-02-19)
binary: rustc
commit-hash: 3246e79513cb89ddbfc0f21cb5a877e5b321dcc5
commit-date: 2024-02-19
host: x86_64-unknown-linux-gnu
release: 1.78.0-nightly
Cranelift version: 0.105.0
bjorn3 commented 7 months ago

Reduced to

#![feature(custom_mir, core_intrinsics)]
#![allow(internal_features)]

use std::intrinsics::mir::*;

fn p(x: u8) {
    println!("{x}");
}

#[custom_mir(dialect = "runtime", phase = "initial")]
pub fn fn0() {
    mir! {
    let _5: u8;
    let _8: i128;
    let _10: isize;
    let _22: ();
    let _23: isize;
    {
    Call(_5 = fn1(), ReturnTo(bb1), UnwindUnreachable())
    }
    bb1 = {
    _10 = _5 as isize;
    _23 = 256isize * _10;
    _5 = _23 as u8;
    Call(_22 = p(_5), ReturnTo(bb2), UnwindUnreachable())
    }
    bb2 = {
    Return()
    }

    }
}

pub fn fn1() -> u8 {
    42
}

pub fn main() {
    fn0();
}
bjorn3 commented 7 months ago

Thanks for the bug report! I've filled https://github.com/bytecodealliance/wasmtime/issues/7999 as this is a Cranelift bug.

bjorn3 commented 7 months ago

The Cranelift fix has been backported.