-
Notifications
You must be signed in to change notification settings - Fork 13.1k
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
passing rust records by value to native functions broken #1402
Comments
The c type unsigned is not the same as the Rust type uint. Try |
I believe you are misreading the commit. I think what that commit says is that "if you are targeting a 64-bit CPU, then |
I found the problem. It looks like rust is passing the record by reference instead of by value. I updated my test to use |
|
Great, that worked! The tutorial said |
I'm reopening this because while passing by-value worked for one pointer value, it's breaking for two. I've updated my gist for a demonstration of the issue. |
This is a whole lot more broken than it looks at first. The reason is subtle. In any calling convention, there's a division of labour between frontend and backend. For clang+LLVM, for example, some decisions are made by the code making LLVM-API calls (which things to pass by pointer or by value) and some decisions are made by the code inside LLVM. It turns out that the place we draw the line is not the same place clang+LLVM draw the line. Which means that when we break clang off and put rustc in its place, we're assuming LLVM is going to be doing a bunch of things magically that it will not. It was expecting clang to make some of those decisions itself. We're not emulating what clang does, so we are operating LLVM in a not-expected way. The result is we're asking LLVM to generate non-system-ABI-conformant calls. The abi is here: http://www.x86-64.org/documentation/abi.pdf and if you scan through to section 3.2.3 on page 15, you'll see there are quite a number of very subtle rules. These combine nontrivially. In particular, in the section on aggregate handling, section 5 (c) is causing your structure (when it's larger than 2 "eightbytes") to spill to memory; clang generates code like this to receive one by return-value, and pass it on by value:
even though it could easily go in registers. It's not of class SSE. This is not something LLVM does for us. The logic for it is in clang, over here: http://llvm.org/svn/llvm-project/cfe/trunk/lib/CodeGen/TargetInfo.cpp if you search for That code in turn appears to be driven by abstract parameter-attributes that are constructed over here http://llvm.org/svn/llvm-project/cfe/trunk/lib/CodeGen/CGCall.cpp, if you search for This sucks and will be a whole lot of work. It's not going to be fixed in time for this release. Thanks to echristo for helping diagnose this. |
lots of changes, here.. should've commited sooner. - added uv::direct module that contains rust fns that map, neatly, to the libuv c library as much as possible. they operate on ptrs to libuv structs mapped in rust, as much as possible (there are some notable exceptions). these uv::direct fns should only take inputs from rust and, as neccesary, translate them into C-friendly types and then pass to the C functions. We want to them to return ints, as the libuv functions do, so we can start tracking status. - the notable exceptions for structs above is due to ref gh-1402, which prevents us from passing structs, by value, across the Rust<->C barrier (they turn to garbage, pretty much). So in the cases where we get back by-val structs from C (uv_buf_init(), uv_ip4_addr(), uv_err_t in callbacks) , we're going to use *ctypes::void (or just errnum ints for uv_err_t) until gh-1402 is resolved. - using crust functions, in these uv::direct fns, for callbacks from libuv, will eschew uv_err_t, if possible, in favor a struct int.. if at all possible (probably isn't.. hm.. i know libuv wants to eventually move to replace uv_err_t with an int, as well.. so hm). - started flushing out a big, gnarly test case to exercise the tcp request side of the uv::direct functions. I'm at the point where, after the connection is established, we write to the stream... when the writing is done, we will read from it, then tear the whole thing down. overall, it turns out that doing "close to the metal" interaction with c libraries is painful (and more chatty) when orchestrated from rust. My understanding is that not much, at all, is written in this fashion in the existant core/std codebase.. malloc'ing in C has been preferred, from what I've gathered. So we're treading new ground, here!
Downgrade string_lit_as_bytes to nursery Between rust-lang#1402 (regarding `to_owned`) and rust-lang#4494 (regarding `impl Read`), as well as other confusion I've seen hit in my work codebase involving string_lit_as_bytes (`"...".as_bytes().into()`), I don't think this lint is at a quality to be enabled by default. I would consider re-enabling this lint after it is updated to understand when the surrounding type information is sufficient to unsize `b"..."` to &\[u8\] without causing a type error. As currently implemented, this lint is pushing people to write `&b"_"[..]` which is not an improvement over `"_".as_bytes()` as far as I am concerned. --- changelog: Remove string_lit_as_bytes from default set of enabled lints
As mentioned in rust-lang#1402.
I thought rust records were supposed to be compatible with c structs, but it seems there is an issue passing them by value to a native module. You can find a example of the bug here:
https://gist.github.com/1543358
The text was updated successfully, but these errors were encountered: