Skip to content

Incorrect code generated from inline assembly with inout register on riscv32im-unknown-none-elf #128212

Closed
@shkoo

Description

@shkoo

I tried compiling this code with a target of riscv32im-unknown-none-elf:

#![no_std]

static mut MY_BUFFER: [u32; 4] = [0u32; 4];

#[no_mangle]
unsafe fn using_inout() {
    let mut start = MY_BUFFER.as_mut_ptr();
    ::core::arch::asm!(
            "ecall",
            inout("a0") start);
    _ = start;
}

The assembly generated is incorrect, since it doesn't add in the lower 16 bits of the address of MY_BUFFER before calling the ecall:

using_inout:
        lui     a0, %hi(example::MY_BUFFER::he36bd30b506a9b69)
        ecall
        ret

As a workaround, changing the inout to inlateout seems to fix the problem:

using_inlateout:
        lui     a0, %hi(example::MY_BUFFER::he36bd30b506a9b69)
        addi    a0, a0, %lo(example::MY_BUFFER::he36bd30b506a9b69)
        ecall
        ret

Here is a compiler explorer link for rust nightly that demonstrates the problem:

https://godbolt.org/z/xMjoTo5oY

(For reference in case it gets fixed in nightly, it's also present in rust 1.80.0)

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.I-unsoundIssue: A soundness hole (worst kind of bug), see: https://en.wikipedia.org/wiki/SoundnessO-riscvTarget: RISC-V architectureP-highHigh priorityllvm-fixed-upstreamIssue expected to be fixed by the next major LLVM upgrade, or backported fixes

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions