Skip to content

Calls from C to Rust get miscompiled on Windows 64 #24427

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
vosen opened this issue Apr 14, 2015 · 6 comments
Closed

Calls from C to Rust get miscompiled on Windows 64 #24427

vosen opened this issue Apr 14, 2015 · 6 comments
Labels
O-windows Operating system: Windows

Comments

@vosen
Copy link
Contributor

vosen commented Apr 14, 2015

Rust code:

#[repr(C)]
pub struct Data {
    bar: u64,
    baz: u64,
}

#[no_mangle]
pub extern fn foo(a1: Data,
                  a2: Data,
                  a3: Data,
                  a4: Data,
                  a5: Data) {
    println!("{:}", a1.bar);
    println!("{:}", a2.bar);
    println!("{:}", a3.bar);
    println!("{:}", a4.bar);
    println!("{:}", a5.bar);
}


extern {
    fn c_main();
}

fn main() {
    unsafe { c_main() };
}

C code:

#include <stdint.h>

typedef struct data {
    uint64_t bar;
    uint64_t baz;
} data;
void foo(data a1,
         data a2,
         data a3,
         data a4,
         data a5);

void c_main(void) {
    data a1;
    a1.bar = 1;
    data a2;
    a2.bar = 2;
    data a3;
    a3.bar = 3;
    data a4;
    a4.bar = 4;
    data a5;
    a5.bar = 5;
    foo(a1, a2, a3, a4, a5);
}

Expected output:

1
2
3
4
5

Actual output:

1
2
3
4
2357776

I couldn't reproduce it with larger number of smaller arguments (eg. passing ten u64s), couldn't reproduce it on 32 bits either. Changing debug/optimization options has no effect.
Works correctly when calling C from C (eg. using this code).
It originally manifested on another 64 bit machine, but I don't have access to it at the moment, though I can get its enviroment too.

LLVM IR: here
Assembly: here
Gcc version: 4.9.2 x86_64-pc-msys (verbose output)
Rust version:

rustc 1.0.0-nightly (6790b0e51 2015-04-11) (built 2015-04-12)
binary: rustc
commit-hash: 6790b0e51967b1487728d155e0800a1ed03a30d3
commit-date: 2015-04-11
build-date: 2015-04-12
host: x86_64-pc-windows-gnu
release: 1.0.0-nightly

Compiled and ran with gcc main.c -c -o libcmain.a && rustc main.rs -l cmain -L. && main.exe

@sfackler sfackler added the O-windows Operating system: Windows label Apr 15, 2015
@vadimcn
Copy link
Contributor

vadimcn commented Apr 16, 2015

Looks like there a slight misunderstanding about the calling convention between GCC and LLVM.
GCC passes a pointer to a5, whereas LLVM expects a5 to be by-value. Changing the last line of foo() to this ↓ produces the expected result.

    unsafe {
        let x5: *const Data = std::mem::transmute(a5.bar);
        println!("{:}", (*x5).bar);
    }

The IR generated by rustc looks correct... unless I am missing some implication of the byval attribute.

define void @foo(%Data* byval, %Data* byval, %Data* byval, 
                 %Data* byval, %Data* byval) unnamed_addr {

Hmm... LLVM codegen bug?

@retep998
Copy link
Member

You forgot to specify the calling convention for your Rust function, so it is using the rust call convention which is different from the C calling convention.
Once you've set the calling convention from both sides to ensure they match up, if it still doesn't work, then you have an actual bug.

@vosen
Copy link
Contributor Author

vosen commented Apr 17, 2015

No, looking at the --pretty=expanded output, function convention correctly defaults to pub extern "win64" fn foo(...).
Also, I forgot to mention in the original post, but, I've tried every calling convention mentioned in the FFI part of the book.

@retep998
Copy link
Member

Okay, I tested this locally, made sure the calling conventions match up, and yet I can still reproduce this issue.

@pravic
Copy link
Contributor

pravic commented Apr 8, 2016

This also was fixed by #29012, btw.

@alexcrichton
Copy link
Member

Yay!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
O-windows Operating system: Windows
Projects
None yet
Development

No branches or pull requests

6 participants