Repository navigation
RISC-V inline assembly ignores clobber constraints #60392
Copy link
Copy link
Closed
Labels
A-LLVMArea: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues.Area: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues.A-inline-assemblyArea: Inline assembly (`asm!(…)`)Area: Inline assembly (`asm!(…)`)C-bugCategory: This is a bug.Category: This is a bug.O-riscvTarget: RISC-V architectureTarget: RISC-V architectureT-compilerRelevant to the compiler team, which will review and decide on the PR/issue.Relevant to the compiler team, which will review and decide on the PR/issue.requires-nightlyThis issue requires a nightly compiler in some way. When possible, use a F-* label instead.This issue requires a nightly compiler in some way. When possible, use a F-* label instead.
Description
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
Metadata
Metadata
Assignees
Labels
A-LLVMArea: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues.Area: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues.A-inline-assemblyArea: Inline assembly (`asm!(…)`)Area: Inline assembly (`asm!(…)`)C-bugCategory: This is a bug.Category: This is a bug.O-riscvTarget: RISC-V architectureTarget: RISC-V architectureT-compilerRelevant to the compiler team, which will review and decide on the PR/issue.Relevant to the compiler team, which will review and decide on the PR/issue.requires-nightlyThis issue requires a nightly compiler in some way. When possible, use a F-* label instead.This issue requires a nightly compiler in some way. When possible, use a F-* label instead.
Activity
lenary commentedon 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 commentedon 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.
cbiffle commentedon 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?
Change RISC-V register names in clobbers.
Change RISC-V register names in clobbers.
lenary commentedon 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 commentedon Feb 14, 2020
Thanks, @lenary! We've worked around this locally in Tock.
Amanieu commentedon 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.