Skip to content

RISC-V inline assembly ignores clobber constraints #60392

Closed

Description

@fintelia

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

Activity

  1. added
    C-bugCategory: This is a bug.
    T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.
    on Apr 30, 2019
  2. added
    A-LLVMArea: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues.
    on Apr 30, 2019
  3. lenary commented on Aug 6, 2019

    @lenary
    Contributor

    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.

  4. lenary commented on Aug 8, 2019

    @lenary
    Contributor

    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.

  5. added
    requires-nightlyThis issue requires a nightly compiler in some way. When possible, use a F-* label instead.
    on Oct 25, 2019
  6. cbiffle commented on Feb 12, 2020

    @cbiffle
    Contributor

    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?

  7. lenary commented on Feb 14, 2020

    @lenary
    Contributor

    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.

  8. cbiffle commented on Feb 14, 2020

    @cbiffle
    Contributor

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

  9. Amanieu commented on May 22, 2020

    @Amanieu
    Member

    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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-LLVMArea: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues.A-inline-assemblyArea: Inline assembly (`asm!(…)`)C-bugCategory: This is a bug.O-riscvTarget: RISC-V architectureT-compilerRelevant 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.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions