rust-lang / rust

Empowering everyone to build reliable and efficient software.
https://www.rust-lang.org
Other
99.2k stars 12.81k forks source link

Unhelpful error message on risc-v using the asm! macro with register extractions #54315

Closed liamnaddell closed 4 years ago

liamnaddell commented 6 years ago

(this is my first issue, sorry)

This is sort of a bug and sort of a feature request/cry for help. All of the following stuff is new to me, so this is probably user error.

The code I tried is attached below diosix.tar.gz

If you take the src/kernel/main.rs function, and replace the a2 with r, the rust compiler no longer segfaults!

I expected some kind of helpful error about how you can't use the a2 register, but got the following beauty:

./build.sh --triple riscv32imac-unknown-none-elf --platform sifive_e
[+] Building for riscv32 SiFive-E series
   Compiling diosix v2.0.0 (/home/liam/repos/diosix)
warning: function is never used: `serial_write`
  --> src/kernel/main.rs:39:1
   |
39 | fn serial_write(s: &str) {
   | ^^^^^^^^^^^^^^^^^^^^^^^^
   |
   = note: #[warn(dead_code)] on by default
error: Could not compile `diosix`.
To learn more, run the command again with --verbose.
make: *** [Makefile:2: all] Error 101

when the --verbose flag is added, you get

./build.sh --triple riscv32imac-unknown-none-elf --platform sifive_e
[+] Building for riscv32 SiFive-E series
       Fresh version_check v0.1.4
       Fresh libc v0.2.43
       Fresh ucd-util v0.1.1
       Fresh utf8-ranges v1.0.1
       Fresh bare-metal v0.2.3
       Fresh memchr v2.0.2
       Fresh regex-syntax v0.6.2
       Fresh riscv v0.3.0
       Fresh aho-corasick v0.6.8
       Fresh lazy_static v1.1.0
       Fresh thread_local v0.3.6
       Fresh regex v1.0.5
   Compiling diosix v2.0.0 (/home/liam/repos/diosix)
     Running `rustc --crate-name kernel src/kernel/main.rs --color always --crate-type bin --emit=dep-info,link -C opt-level=3 -C panic=abort --cfg 'feature="sifive_e"' -C metadata=332af80c5eb5cf4e -C extra-filename=-332af80c5eb5cf4e --out-dir /home/liam/repos/diosix/target/riscv32imac-unknown-none-elf/release/deps --target riscv32imac-unknown-none-elf -C ar=riscv32-elf-ar -C linker=riscv32-elf-ld -L dependency=/home/liam/repos/diosix/target/riscv32imac-unknown-none-elf/release/deps -L dependency=/home/liam/repos/diosix/target/release/deps --extern riscv=/home/liam/repos/diosix/target/riscv32imac-unknown-none-elf/release/deps/libriscv-9f27c1cf8cae7478.rlib -C link-arg=-Tsrc/platform/riscv32/sifive_e/link.ld -L native=/home/liam/repos/diosix/target/riscv32imac-unknown-none-elf/release/build/diosix-8a0e4656ce8eac69/out -l static=entry`
warning: function is never used: `serial_write`
  --> src/kernel/main.rs:39:1
   |
39 | fn serial_write(s: &str) {
   | ^^^^^^^^^^^^^^^^^^^^^^^^
   |
   = note: #[warn(dead_code)] on by default
error: Could not compile `diosix`.
Caused by:
  process didn't exit successfully: `rustc --crate-name kernel src/kernel/main.rs --color always --crate-type bin --emit=dep-info,link -C opt-level=3 -C panic=abort --cfg 'feature="sifive_e"' -C metadata=332af80c5eb5cf4e -C extra-filename=-332af80c5eb5cf4e --out-dir /home/liam/repos/diosix/target/riscv32imac-unknown-none-elf/release/deps --target riscv32imac-unknown-none-elf -C ar=riscv32-elf-ar -C linker=riscv32-elf-ld -L dependency=/home/liam/repos/diosix/target/riscv32imac-unknown-none-elf/release/deps -L dependency=/home/liam/repos/diosix/target/release/deps --extern riscv=/home/liam/repos/diosix/target/riscv32imac-unknown-none-elf/release/deps/libriscv-9f27c1cf8cae7478.rlib -C link-arg=-Tsrc/platform/riscv32/sifive_e/link.ld -L native=/home/liam/repos/diosix/target/riscv32imac-unknown-none-elf/release/build/diosix-8a0e4656ce8eac69/out -l static=entry` (signal: 11, SIGSEGV: invalid memory reference)
make: *** [Makefile:2: all] Error 101

It is totally unclear to me what registers are allowed to be used where(this is because I have no idea what I am doing).

btw im on nightly: rustc 1.30.0-nightly (2ab3eba30 2018-09-14) btw here is the code this is all based off of: "https://github.com/diodesign/diosix" I really love rust-lang and I would love to hear back :)

liamnaddell commented 6 years ago

wtf

liamnaddell commented 6 years ago

I think this is b/c there is no type checking on the asm! macro's outputs

liamnaddell commented 6 years ago

This code also works when using the x(n) versions of registers instead of t0, a0 and other stuff like that

levex commented 6 years ago

@liamnaddell hi, could you please upload the relevant source code to https://play.rust-lang.org/ ?

I don't really trust random archives on the internet :)

liamnaddell commented 6 years ago

I really can't I'm sorry.

It uses separate asm files, and a build.sh and build.rs script for building. It also ships with multiple linker scripts

liamnaddell commented 6 years ago

It's a bare-metal risc-v elf binary, not an app u run on your system, you need qemu

levex commented 6 years ago

It failed to build for the sifive_e platform (a board which I happen to have):

[+] Building for riscv32 SiFive-E series
       Fresh version_check v0.1.4
       Fresh libc v0.2.43
       Fresh ucd-util v0.1.1
       Fresh utf8-ranges v1.0.1
       Fresh bare-metal v0.2.3
       Fresh memchr v2.0.2
       Fresh regex-syntax v0.6.2
       Fresh riscv v0.3.0
       Fresh aho-corasick v0.6.8
       Fresh lazy_static v1.1.0
       Fresh thread_local v0.3.6
       Fresh regex v1.0.5
   Compiling diosix v2.0.0 (/data/rust/rust-lang-rust/issues/misc/diosix)
     Running `/data/rust/rust-lang-rust/issues/misc/diosix/target/release/build/diosix-631a70b0814a0e1c/build-script-build`
error: failed to run custom build command for `diosix v2.0.0 (/data/rust/rust-lang-rust/issues/misc/diosix)`
process didn't exit successfully: `/data/rust/rust-lang-rust/issues/misc/diosix/target/release/build/diosix-631a70b0814a0e1c/build-script-build` (exit code: 101)
--- stdout
cargo:rerun-if-changed=src/platform/riscv32/sifive_e/link.ld
cargo:rerun-if-changed=src/platform/riscv32/sifive_e/asm/entry.s

--- stderr
thread 'main' panicked at 'Failed to assemble src/platform/riscv32/sifive_e/asm/entry.s: Os { code: 2, kind: NotFound, message: "No such file or directory" }', libcore/result.rs:1009:5
note: Run with `RUST_BACKTRACE=1` for a backtrace.

But I reproduced your issue with the spike platform:

[+] Building for riscv32 Spike emulator
       Fresh version_check v0.1.4
       Fresh libc v0.2.43
       Fresh ucd-util v0.1.1
       Fresh utf8-ranges v1.0.1
       Fresh bare-metal v0.2.3
       Fresh memchr v2.0.2
       Fresh regex-syntax v0.6.2
       Fresh riscv v0.3.0
       Fresh aho-corasick v0.6.8
       Fresh lazy_static v1.1.0
       Fresh thread_local v0.3.6
       Fresh regex v1.0.5
   Compiling diosix v2.0.0 (/data/rust/rust-lang-rust/issues/misc/diosix)
     Running `rustc --crate-name kernel src/kernel/main.rs --color never --crate-type bin --emit=dep-info,link -C opt-level=3 -C panic=abort --cfg 'feature="spike"' -C metadata=dd9000a3a945a083 -C extra-filename=-dd9000a3a945a083 --out-dir /data/rust/rust-lang-rust/issues/misc/diosix/target/riscv32imac-unknown-none-elf/release/deps --target riscv32imac-unknown-none-elf -C ar=riscv32-elf-ar -C linker=riscv32-elf-ld -L dependency=/data/rust/rust-lang-rust/issues/misc/diosix/target/riscv32imac-unknown-none-elf/release/deps -L dependency=/data/rust/rust-lang-rust/issues/misc/diosix/target/release/deps --extern riscv=/data/rust/rust-lang-rust/issues/misc/diosix/target/riscv32imac-unknown-none-elf/release/deps/libriscv-88d9c8be593b66e4.rlib -C link-arg=-Tsrc/platform/riscv32/spike/link.ld`
warning: function is never used: `serial_write`
  --> src/kernel/main.rs:39:1
   |
39 | fn serial_write(s: &str) {
   | ^^^^^^^^^^^^^^^^^^^^^^^^
   |
   = note: #[warn(dead_code)] on by default

error[E0668]: malformed inline assembly
  --> src/kernel/main.rs:27:9
   |
27 |         asm!("li $0,-1" :"=a2"(r) ::: "volatile");
   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: aborting due to previous error

For more information about this error, try `rustc --explain E0668`.
error: Could not compile `diosix`.

Caused by:
  process didn't exit successfully: `rustc --crate-name kernel src/kernel/main.rs --color never --crate-type bin --emit=dep-info,link -C opt-level=3 -C panic=abort --cfg 'feature="spike"' -C metadata=dd9000a3a945a083 -C extra-filename=-dd9000a3a945a083 --out-dir /data/rust/rust-lang-rust/issues/misc/diosix/target/riscv32imac-unknown-none-elf/release/deps --target riscv32imac-unknown-none-elf -C ar=riscv32-elf-ar -C linker=riscv32-elf-ld -L dependency=/data/rust/rust-lang-rust/issues/misc/diosix/target/riscv32imac-unknown-none-elf/release/deps -L dependency=/data/rust/rust-lang-rust/issues/misc/diosix/target/release/deps --extern riscv=/data/rust/rust-lang-rust/issues/misc/diosix/target/riscv32imac-unknown-none-elf/release/deps/libriscv-88d9c8be593b66e4.rlib -C link-arg=-Tsrc/platform/riscv32/spike/link.ld` (exit code: 1)

Seems fixed. :-)

lenary commented 5 years ago

Using a reduced version of the same issue, here, the issue with the inline assembly has not gone away, but the error messages are much better. Sadly, you can't provide --target to play.rust-lang.org, even if you do only want to generate llvm IR, so it's hard to show.

For reference, the way to fix the inline assembly is to write the input constraint with braces (and, at the moment, due to a bug, using the architectural register name x12) ={x12}, as documented in the LLVM IR reference. Rust's asm! macro is a thin shim on top of this, and this has subtly different features to the inline assembly that GCC supports.

liamnaddell commented 5 years ago

Thanks for your response :)

Amanieu commented 4 years ago

This issue does not apply to the new asm! (RFC 2850).

The legacy llvm_asm! is deprecated and is no longer maintained.