compiler_builtins for __floatdisf and __floatdidf are not correctly generated, causing stack overflow due to infinite recursion
This is the smallest piece of code needed to replicate a double fault error. The problem arises when converting timestamp, an i64 variable, to f64. If you set timestamp to be u64 before converting, then the double fault does not appear.
The DF also only arises when you print timestamp to the screen, or if you do operations with it and print those variables, so the problem may be with the println! macro
#![no_std]
#![feature(slice_concat_ext)]
#[macro_use] extern crate terminal_print;
extern crate http_client;
use http_client::{millis_since};
#[no_mangle]
fn main() {
let startup_time: u64 = 9000000000000; //this can be any u64 value
let timestamp = match millis_since(startup_time) {
Ok(time) => time as i64,
Err(err) => return println!("couldn't get timestamp:{}", err),
};
// it's during this conversion of timestamp from i64 to f64 that the double fault occurs
println!("timestamp:{}", timestamp as f64);
}
is the whole hpet usage necessary? Or can we just replicate it with a constant u64 value?
hpet is necessary, otherwise the DF doesn't appear
actually I just tried it again, hpet is NOT needed to replicate the DF, any u64 value works
Great, can you update the minimal example to reflect that?
I encounter the same problem and found a bug in builtin function. Here is my gdb output:
(gdb) step
298 WINDOW_BORDER_COLOR_INNER, (dx+dy) as f32 / f32_window_border_size));
(gdb) s
__floatdisf (i=0) at /home/heterofpga/.cargo/git/checkouts/compiler-builtins-ec094dc45a0179c8/045de6e/src/float/conv.rs:91
91 if cfg!(target_arch = "x86_64") {
(gdb) s
92 i as f32
(gdb) s
__floatdisf (i=0) at /home/heterofpga/.cargo/git/checkouts/compiler-builtins-ec094dc45a0179c8/045de6e/src/float/conv.rs:91
91 if cfg!(target_arch = "x86_64") {
(gdb) s
92 i as f32
(gdb) s
__floatdisf (i=0) at /home/heterofpga/.cargo/git/checkouts/compiler-builtins-ec094dc45a0179c8/045de6e/src/float/conv.rs:91
91 if cfg!(target_arch = "x86_64") {
(gdb) s
92 i as f32
(gdb) s
__floatdisf (i=0) at /home/heterofpga/.cargo/git/checkouts/compiler-builtins-ec094dc45a0179c8/045de6e/src/float/conv.rs:91
91 if cfg!(target_arch = "x86_64") {
(gdb) s
92 i as f32
(gdb) s
__floatdisf (i=0) at /home/heterofpga/.cargo/git/checkouts/compiler-builtins-ec094dc45a0179c8/045de6e/src/float/conv.rs:91
91 if cfg!(target_arch = "x86_64") {
(gdb) s
92 i as f32
(gdb) s
__floatdisf (i=0) at /home/heterofpga/.cargo/git/checkouts/compiler-builtins-ec094dc45a0179c8/045de6e/src/float/conv.rs:91
91 if cfg!(target_arch = "x86_64") {
(gdb) s
92 i as f32
(gdb) s
__floatdisf (i=0) at /home/heterofpga/.cargo/git/checkouts/compiler-builtins-ec094dc45a0179c8/045de6e/src/float/conv.rs:91
91 if cfg!(target_arch = "x86_64") {
(gdb) s
92 i as f32
(gdb) s
__floatdisf (i=0) at /home/heterofpga/.cargo/git/checkouts/compiler-builtins-ec094dc45a0179c8/045de6e/src/float/conv.rs:91
91 if cfg!(target_arch = "x86_64") {
(gdb) s
92 i as f32
(gdb) bt
#0 __floatdisf (i=0) at /home/heterofpga/.cargo/git/checkouts/compiler-builtins-ec094dc45a0179c8/045de6e/src/float/conv.rs:92
#1 0xffffffff80816c3c in __floatdisf (i=0)
at /home/heterofpga/.cargo/git/checkouts/compiler-builtins-ec094dc45a0179c8/045de6e/src/float/conv.rs:92
#2 0xffffffff80816c3c in __floatdisf (i=0)
at /home/heterofpga/.cargo/git/checkouts/compiler-builtins-ec094dc45a0179c8/045de6e/src/float/conv.rs:92
#3 0xffffffff80816c3c in __floatdisf (i=0)
at /home/heterofpga/.cargo/git/checkouts/compiler-builtins-ec094dc45a0179c8/045de6e/src/float/conv.rs:92
#4 0xffffffff80816c3c in __floatdisf (i=0)
at /home/heterofpga/.cargo/git/checkouts/compiler-builtins-ec094dc45a0179c8/045de6e/src/float/conv.rs:92
#5 0xffffffff80816c3c in __floatdisf (i=0)
at /home/heterofpga/.cargo/git/checkouts/compiler-builtins-ec094dc45a0179c8/045de6e/src/float/conv.rs:92
#6 0xffffffff80816c3c in __floatdisf (i=0)
at /home/heterofpga/.cargo/git/checkouts/compiler-builtins-ec094dc45a0179c8/045de6e/src/float/conv.rs:92
#7 0xffffffff80816c3c in __floatdisf (i=0)
at /home/heterofpga/.cargo/git/checkouts/compiler-builtins-ec094dc45a0179c8/045de6e/src/float/conv.rs:92
#8 0xffffffff801edd5e in window_manager_alpha::WindowManagerAlpha::refresh_single_pixel_with_buffer (
self=0xffffffff8084c040 <window_manager_alpha::WINDOW_MANAGER+16>, x=20, y=20) at kernel/window_manager_alpha/src/lib.rs:298
#9 0xffffffff801ef71b in window_manager_alpha::WindowManagerAlpha::refresh_rect_border (
self=0xffffffff8084c040 <window_manager_alpha::WINDOW_MANAGER+16>, x_start=20, x_end=1260, y_start=20, y_end=1004)
at kernel/window_manager_alpha/src/lib.rs:381
#10 0xffffffff801f21f5 in window_manager_alpha::WindowManagerAlpha::refresh_floating_border (
self=0xffffffff8084c040 <window_manager_alpha::WINDOW_MANAGER+16>, show=true, x_start=20, x_end=1260, y_start=20, y_end=1004)
at kernel/window_manager_alpha/src/lib.rs:516
it shows a recursive function call that will ultimately make stack overflow. further look at the function it says:
#[arm_aeabi_alias = __aeabi_l2f]
pub extern "C" fn __floatdisf(i: i64) -> f32 {
// On x86_64 LLVM will use native instructions for this conversion, we
// can just do it directly
if cfg!(target_arch = "x86_64") {
i as f32
} else {
int_to_float!(i, i64, f32)
}
}
the cfg!(target_arch = "x86_64") { condition will call i as f32 which exactly call the function __floatdisf(i: i64) -> f32
The root problem as identified above is that the functions as generated within the compiler_builtins crate for __floatdisf (u64 -> f32) and __floatdidf (u64 -> f64) are supposed to be compiled into native instructions, but that isn't happening. I presume this is due to the Theseus target json config file specifying disabling mmx/sse and enabling +soft_float.
The actual problem is stack overflow due to infinite recursion, which we should deal with separately (see #17).
I'm not sure how to fix the definition of these functions, since it's a problem with a builtin crate within Rust itself. Probably best to file an issue.
Minimal example here:
#![no_std]
extern crate alloc;
#[macro_use] extern crate terminal_print;
use alloc::{vec::Vec, string::String};
pub fn main(_: Vec<String>) -> isize {
let u64_value: u64 = 9000000000000;
println!("trying to convert u64_value {:?} to f64...", u64_value);
println!("u64_value as f64: {:?}", u64_value as f64); // <-- this works correctly
let i64_value: i64 = 1000000000000;
println!("trying to convert i64_value {:?} to f64...", i64_value);
println!("i64_value as f64: {:?}", i64_value as f64); // ** <-- this fails, __floatdidf recurses infinitely **
println!("trying to convert i64_value {:?} to f32...", i64_value);
// this also fails
println!("i64_value as f32: {:?}", i64_value as f32); // ** <-- this fails, __floatdisf recurses infinitely **
0
}
I don't think there's much we can do for this besides wait for rustc to fix it, or submit such a fix ourselves to the compiler_builtins repo.
This has been solved in more recent compiler versions and no longer occurs.