Skip to content

In latest nightly observing a to-be returned variable changes its value. #84667

Closed
@JAicewizard

Description

@JAicewizard

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.

Metadata

Metadata

Assignees

Labels

A-LLVMArea: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues.E-needs-mcveCall for participation: This issue has a repro, but needs a Minimal Complete and Verifiable ExampleT-compilerRelevant to the compiler team, which will review and decide on the PR/issue.regression-from-stable-to-betaPerformance or correctness regression from stable to beta.

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions