Description
Code
I have not been able to reproduce this with pure c code. I found this while working with cgo+rust, and managed to make a small-ish reproducible setup.
I tried this code:
lib.rs
use softposit::{P32, P16};
#[no_mangle] pub extern "C" fn positdiv32(a: u32, b:u32) -> u32{
let a = P32::from_bits(a);
let b = P32::from_bits(b);
let c = a/b;
let x = c.to_bits();
// if x >> 31 == 0{
// print!("hey!\n");
// }
// print!("{:}\n",x);
x
}
toml file
[package]
name = "positrs"
version = "0.1.0"
authors = ["jaap aarts <[email protected]>"]
edition = "2018"
[lib]
crate-type = ["cdylib"]
[dependencies]
softposit = "0.3.9"
positrs.h
#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
uint32_t positdiv32(uint32_t a, uint32_t b);
c file
#include <stdio.h>
#include <stdint.h>
#include "positrs.h"
void binprintf(uint32_t v)
{
unsigned int mask=1<<((sizeof(int)<<3)-1);
while(mask) {
printf("%d", (v&mask ? 1 : 0));
mask >>= 1;
}
}
void main(){
uint32_t a = 0b11000100001110111011110011001000;
uint32_t b = 0b01011111011001010011000111110001;
uint32_t c = positdiv32(a,b);
binprintf(c);
}
run
cargo build --release
cp target/release/libpositrs.so .
gcc -g main.c -o call_rust -L. -lpositrs
LD_LIBRARY_PATH=. ./call_rust
And you will see that this prints 00011110000111010100101001000110⏎
This is (to me) clearly wrong since dividing a negative number with a positive number should be a negative number, and this is a positive number.
So I tried to print the variable in rust, see where it went wrong...
Uncomment the printf!(...)
line and run the following commands
cargo build --release
cp target/release/libpositrs.so .
LD_LIBRARY_PATH=. ./call_rust
and this luckely prints the exact same binary value....
3789731258
11100001111000101011010110111010⏎
oh.
somehow adding the print statement changes the return value of the function when exported to C.
The second one is correct, the first is not.
I also tried just observing x, without actually printing it, using the if
statement above the print!
and it had the same result as the print!
I expected to see this happen:
I expected the value to be the same no-matter what if the value is being observed, and this to be the correct value of 0b11100001111000101011010110111010
Instead, this happened: explanation
Instead I got the wrong number after updating to the latest nightly.
Version it worked on
Currently I know for sure it works on rustc 1.52.0-beta.6 (f97769a2b 2021-04-27)
It also previously worked on nightly, but I dont think I can see the version history.
Version with regression
current broken nightly version: rustc 1.53.0-nightly (42816d61e 2021-04-24)
rustc --version --verbose
:
rustc 1.52.0-beta.6 (f97769a2b 2021-04-27)
binary: rustc
commit-hash: f97769a2b7bc5a6b3d8f7140613cf26352f2b518
commit-date: 2021-04-27
host: x86_64-unknown-linux-gnu
release: 1.52.0-beta.6
LLVM version: 12.0.0
The compiler did not crash.