Closed
Description
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
Metadata
Metadata
Assignees
Type
Projects
Milestone
Relationships
Development
No branches or pull requests
Activity
vadimcn commentedon 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 expectsa5
to be by-value. Changing the last line offoo()
to this ↓ produces the expected result.The IR generated by rustc looks correct... unless I am missing some implication of the
byval
attribute.Hmm... LLVM codegen bug?
retep998 commentedon Apr 17, 2015
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 commentedon Apr 17, 2015
No, looking at the
--pretty=expanded
output, function convention correctly defaults topub 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 commentedon Apr 17, 2015
Okay, I tested this locally, made sure the calling conventions match up, and yet I can still reproduce this issue.
pravic commentedon Apr 8, 2016
This also was fixed by #29012, btw.
alexcrichton commentedon Apr 8, 2016
Yay!