Skip to content
New issue

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

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

Already on GitHub? # to your account

RISC-V inline assembly ignores clobber constraints #60392

Closed
fintelia opened this issue Apr 30, 2019 · 6 comments
Closed

RISC-V inline assembly ignores clobber constraints #60392

fintelia opened this issue Apr 30, 2019 · 6 comments
Labels
A-inline-assembly Area: Inline assembly (`asm!(…)`) A-LLVM Area: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues. C-bug Category: This is a bug. O-riscv Target: RISC-V architecture requires-nightly This issue requires a nightly compiler in some way. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@fintelia
Copy link
Contributor

This code:

#![no_std]
#![feature(asm)]
#![feature(start)]
#![feature(lang_items)]

#[lang = "eh_personality"] extern fn eh_personality() {}
#[panic_handler] fn panic(info: &::core::panic::PanicInfo) -> ! { loop {} }
#[start] fn start(_argc: isize, _argv: *const *const u8) -> isize {0}
#[no_mangle] pub fn abort() -> ! { loop {} }

#[no_mangle]
pub fn _start(a: [u32; 6]) {
    unsafe {
        asm!("mv a0, $0
              mv a1, $1
              mv a2, $2
              mv a3, $3
              mv a4, $4
              mv a5, $5"
             :: "r"(a[0]),
             "r"(a[1]),
             "r"(a[2]),
             "r"(a[3]),
             "r"(a[4]),
             "r"(a[5])
             : "a0",
             "a1",
             "a2",
             "a3",
             "a4",
             "a5"
        );
    }
}

When compiled for the riscv64imac target (and other riscv targets):

$ cargo rustc --release --target riscv64imac-unknown-none-elf

Produces code which uses the clobbered registers to pass in values, resulting in the inputs being overwritten before they can be used:

0000000000011000 <_start>:
   11000:	01456583          	lwu	a1,20(a0)
   11004:	01056603          	lwu	a2,16(a0)
   11008:	00c56683          	lwu	a3,12(a0)
   1100c:	00856703          	lwu	a4,8(a0)
   11010:	00456783          	lwu	a5,4(a0)
   11014:	00056503          	lwu	a0,0(a0)
   11018:	852a                	mv	a0,a0
   1101a:	85be                	mv	a1,a5
   1101c:	863a                	mv	a2,a4
   1101e:	86b6                	mv	a3,a3
   11020:	8732                	mv	a4,a2
   11022:	87ae                	mv	a5,a1
   11024:	8082                	ret

See also: #60391

@Centril Centril added A-inline-assembly Area: Inline assembly (`asm!(…)`) O-riscv Target: RISC-V architecture labels Apr 30, 2019
@jonas-schievink jonas-schievink added C-bug Category: This is a bug. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Apr 30, 2019
@nagisa nagisa added the A-LLVM Area: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues. label Apr 30, 2019
@lenary
Copy link
Contributor

lenary commented Aug 6, 2019

Digging into this issue, it seems if you use the canonical register names in the clobber list (i.e., x10-x15) then you see the correct behaviour. I'm going to start working on a patch to cover this behaviour so that you can use register aliases, but I'm not sure if the patch will be to rustc or to llvm itself. I'll keep this issue updated as progress is made.

@lenary
Copy link
Contributor

lenary commented Aug 8, 2019

I have just landed https://reviews.llvm.org/rL368303, which solves the problem of using abi names for you on RISC-V. This has not been backported to the 9.0 branch, and I don't know if we plan to, so you might have to wait a little bit for this to work. Sadly I couldn't find a cross-target way of doing this, so the same issue will arise on Mips.

@Centril Centril added the requires-nightly This issue requires a nightly compiler in some way. label Oct 25, 2019
@cbiffle
Copy link
Contributor

cbiffle commented Feb 12, 2020

We're still hitting this in RISC-V Tock with a January-2020-ish nightly compiler. Has the Apr 2019 LLVM fix not made it into rustc yet, or could it be a new bug?

cbiffle added a commit to oxidecomputer/libtock-rs that referenced this issue Feb 12, 2020
As of right now, asm clobbers of specific registers in Rust only work
with the registers' x-style names, not the a/t/ra names.

See rust-lang/rust#60392.
cbiffle added a commit to oxidecomputer/libtock-rs that referenced this issue Feb 13, 2020
As of right now, asm clobbers of specific registers in Rust only work
with the registers' x-style names, not the a/t/ra names.

Fixes tock#139.

See rust-lang/rust#60392.
@lenary
Copy link
Contributor

lenary commented Feb 14, 2020

LLVM 10.0 has not yet been released (but there are release candidates for it)

I think rust-lang is still using https://github.com/rust-lang/llvm-project/tree/rustc/9.0-2019-12-19 (judging by the .gitmodules on rust-lang's master). This does not contain the commit that fixed the problem.

The good news is it looks like rust-lang is getting ready to update to LLVM 10.0 (you'll see there's a 10.0 branch in rust-lang/llvm-project), and that branch does contain the fix.

@cbiffle
Copy link
Contributor

cbiffle commented Feb 14, 2020

Thanks, @lenary! We've worked around this locally in Tock.

@Amanieu
Copy link
Member

Amanieu commented May 22, 2020

This issue does not apply to the new asm! (RFC 2850) which properly handles register names for operands.

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

@Amanieu Amanieu closed this as completed May 22, 2020
# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
A-inline-assembly Area: Inline assembly (`asm!(…)`) A-LLVM Area: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues. C-bug Category: This is a bug. O-riscv Target: RISC-V architecture requires-nightly This issue requires a nightly compiler in some way. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests

7 participants