ziglang / zig

General-purpose programming language and toolchain for maintaining robust, optimal, and reusable software.
https://ziglang.org
MIT License
33.59k stars 2.46k forks source link

Unable to use `callconv(.Interrupt)` for riscv targets #20671

Open akiroz opened 1 month ago

akiroz commented 1 month ago

Zig Version

0.13.0

Steps to Reproduce and Observed Behavior

Currently compiling this function for riscv targets will yield the following error:

export fn _irq() callconv(.Interrupt) void {
    asm volatile ("nop");
}
error: callconv 'Interrupt' is only available on x86, x86_64, AVR, and MSP430, not riscv32

irq routines in riscv requires a different mret instruction at the end and this is achieved in C as in the following:

void _irq() __attribute__((interrupt)) {
    asm ("nop");
}

for which LLVM generates the following code:

000111e0 <_irq>:
   111e0:       1141                    addi    sp,sp,-16
   111e2:       c606                    sw      ra,12(sp)
   111e4:       c422                    sw      s0,8(sp)
   111e6:       0800                    addi    s0,sp,16
   111e8:       0001                    nop
   111ea:       40b2                    lw      ra,12(sp)
   111ec:       4422                    lw      s0,8(sp)
   111ee:       0141                    addi    sp,sp,16
   111f0:       30200073                mret

I dont know enough about zig/llvm internals to know if the zig callconv(.Interrupt) has anything to do with the way C's attributes are handled wrt llvm but it'll be useful to be able to implement riscv irq routines in pure zig.

Expected Behavior

Able to use callconv(.Interrupt) on riscv targets.

Vexu commented 1 month ago

Looks like there are three modes of interrupts https://clang.llvm.org/docs/AttributeReference.html#interrupt-risc-v

LLVM implements them as function attributes rather than calling conventions, I'm guessing we would add InterruptUser, InterruptSupervisor and InterruptMachine and have Interrupt alias InterruptMachine.