-
Notifications
You must be signed in to change notification settings - Fork 10
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
ABI 'o32' is incompatible with target ABI 'n64' #30
Comments
At least on other linkers such as GNU Linker, I've always had to compile the code with Does it fail on building with o32? |
Hmm, I'm not sure how to get Rust to build |
In PR #20, although this is not likely to be merged, I was able to link o32 newlib in without any issues. So it's definitely worked in the past. |
@command-tab You can build with FWIW I had this same error from lld before I added the The other workaround is just building with lto disabled. :( |
I did manage to get that command, locate rust-lld, and run it verbosely:
I tried building with lto off in my example, but that didn't seem to have any effect. I had this in my Cargo.toml at
Should I be installing and running cargo-n64 with lto off, not my example? It also strikes me that I may not even be using the release profile. I should probably step back and get more familiar with Cargo.toml before jumping into the deep end 😂 Thanks for the help so far! |
You are linking against nusys. Personally I've never tried this! Don't know what to expect. But I believe that rust-lang/cargo#8066 has given us some trouble recently, and you might be seeing similar issues. For more context on that change, see rust-lang/rust#66961 LTO on the cargo-n64 build won't change the behavior here. And don't worry about whether you're using the release profile; Now that you have the list of library archive files, you could extract each one with |
@command-tab I found today that diff --git a/cargo-n64/src/templates/mips-nintendo64-none.fmt b/cargo-n64/src/templates/mips-nintendo64-none.fmt
index 77a7ab5..a01b497 100644
--- a/cargo-n64/src/templates/mips-nintendo64-none.fmt
+++ b/cargo-n64/src/templates/mips-nintendo64-none.fmt
@@ -1,14 +1,15 @@
{{
"arch": "mips",
"cpu": "mips3",
- "data-layout": "E-m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32:64-S64",
+ "data-layout": "E-m:m-p:64:64-i8:8:32-i16:16:32-i64:64-n64-S64",
"disable-redzone": true,
"env": "unknown",
"executables": true,
- "features": "+mips3,+gp64,+fpxx,+nooddspreg",
+ "features": "+mips3,+gp64",
"linker": "rust-lld",
"linker-flavor": "ld.lld",
"llvm-target": "mips-unknown-unknown",
+ "llvm-abiname": "n64",
"os": "none",
"panic-strategy": "abort",
"pre-link-args": {{
@@ -17,8 +18,8 @@
]
}},
"relocation-model": "static",
- "target-c-int-width": "32",
+ "target-c-int-width": "64",
"target-endian": "big",
- "target-pointer-width": "32",
+ "target-pointer-width": "64",
"vendor": "nintendo64"
}} I didn't notice any differences in a disassembler, and the hello-ipl3font example still works with this target configuration. I did not attempt to link it with nusys. Strange that there is no discernible difference. Even the o32 binaries pass more than 4 arguments as registers. I've tested up to 10 args, and all are passed as registers ( |
Cool, thanks! I'll check it out 👀 |
I ran into this same problem trying to write some rust functions to pull into an existing C project using libdragon, I used the patched mips-nintendo64-none.json it compiles and I can link it, and it seems to run, but only until I try to do real work with it. I can pass parameters like size_t/usize back and forth, but not pointers like
No matter how I change mips-nintendo64-none.json, rust still calls this (seemingly wrong) way. I tried building myself a 32-bit C toolchain and using the original mips-nintendo64-none.json from this project where the calling convention matches, but libdragon won't build successfully that way. At this point I'm at the end of my rope here trying to figure this out and hoping someone else will be able to help. Thanks for any pointers (pun intended) you can give me. |
The disassembly for both C and Rust functions looks fine. C just allocates more stack space (unnecessarily) but they are otherwise identical. Part of the problem here is that you are blindly passing a pointer argument from the caller, so these don't show how the address is produced. Compiling something like these examples might be more useful: void call_test() {
screen_text("Hello, world!");
} extern "C" {
fn screen_text(msg: *const u8);
}
#[no_mangle]
pub extern "C" fn rust_call_test() {
let msg = "Hello, world!\0".as_bytes().as_ptr();
unsafe { screen_text(msg); }
} I tried to get the godbolt compiler to output something resembling the custom target. But I don't think rustc codegen options has everything needed for all cases. This code is simple enough that it should be very close: https://godbolt.org/z/nWvfMPYY9 rust_call_test:
addiu $sp, $sp, -24
sw $ra, 20($sp)
lui $1, %hi($__unnamed_1)
jal screen_text
addiu $4, $1, %lo($__unnamed_1)
lw $ra, 20($sp)
jr $ra
addiu $sp, $sp, 24
$__unnamed_1:
.asciz "Hello, world!" No surprises here, |
The use of 64-bit instruction is interesting. I think the |
Compiled the new examples:
I tried changing data-layout a bit but rust still wants to compile to these |
This project is pinned to an old nightly Rust: Line 1 in 72019a0
I can't keep it up to date as frequently as I would like because getting out the N64 all the time is a pain. But I suspect another round of updates like #38 is sorely needed. That might also require some changes to |
I'm attempting to link in a Nintendo 64 SDK static library (
libnusys.a
), but the Rust linker errors out:Do you think I ought be producing
o32
ABI binaries instead ofn64
ones to match the static library? I'm curious what you make of this.Here's my
build.rs
:Thanks!
The text was updated successfully, but these errors were encountered: