Skip to content

Allow extern "C" #336

New issue

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

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

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Aug 7, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions riscv-rt/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
`a2` is preserved in `a5`, as there are only two callee-saved registers.
New documentation of startup functions (`_mp_hook` and `__pre_init`) now provide
additional implementation guidelines to ensure a correct behavior of the runtime.
- Allow `extern "C"` functions for exceptions, core-interrupts and external-interrupts.

### Removed

Expand Down
19 changes: 13 additions & 6 deletions riscv-rt/macros/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -688,8 +688,8 @@ impl RiscvPacItem {

fn valid_signature(&self) -> &str {
match self {
Self::Exception => "`[unsafe] fn([&[mut] riscv_rt::TrapFrame]) [-> !]`",
_ => "`[unsafe] fn() [-> !]`",
Self::Exception => "`[unsafe] [extern \"C\"] fn([&[mut] riscv_rt::TrapFrame]) [-> !]`",
_ => "`[unsafe] [extern \"C\"] fn() [-> !]`",
}
}

Expand Down Expand Up @@ -719,7 +719,14 @@ impl RiscvPacItem {
&& f.sig.constness.is_none()
&& f.sig.asyncness.is_none()
&& f.vis == Visibility::Inherited
&& f.sig.abi.is_none()
&& match &f.sig.abi {
None => true,
Some(syn::Abi {
extern_token: _,
name: Some(name),
}) if name.value() == "C" => true,
_ => false,
}
&& f.sig.generics.params.is_empty()
&& f.sig.generics.where_clause.is_none()
&& f.sig.variadic.is_none()
Expand All @@ -741,7 +748,7 @@ impl RiscvPacItem {
#[proc_macro_attribute]
/// Attribute to declare an exception handler.
///
/// The function must have the signature `[unsafe] fn([&[mut] riscv_rt::TrapFrame]) [-> !]`.
/// The function must have the signature `[unsafe] [extern "C"] fn([&[mut] riscv_rt::TrapFrame]) [-> !]`.
///
/// The argument of the macro must be a path to a variant of an enum that implements the `riscv_rt::ExceptionNumber` trait.
///
Expand All @@ -760,7 +767,7 @@ pub fn exception(args: TokenStream, input: TokenStream) -> TokenStream {
#[proc_macro_attribute]
/// Attribute to declare a core interrupt handler.
///
/// The function must have the signature `[unsafe] fn() [-> !]`.
/// The function must have the signature `[unsafe] [extern "C"] fn() [-> !]`.
///
/// The argument of the macro must be a path to a variant of an enum that implements the `riscv_rt::CoreInterruptNumber` trait.
///
Expand All @@ -787,7 +794,7 @@ pub fn core_interrupt(args: TokenStream, input: TokenStream) -> TokenStream {
#[proc_macro_attribute]
/// Attribute to declare an external interrupt handler.
///
/// The function must have the signature `[unsafe] fn() [-> !]`.
/// The function must have the signature `[unsafe] [extern "C"] fn() [-> !]`.
///
/// The argument of the macro must be a path to a variant of an enum that implements the `riscv_rt::ExternalInterruptNumber` trait.
///
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
error: `#[core_interrupt]` function must have signature `[unsafe] fn() [-> !]`
error: `#[core_interrupt]` function must have signature `[unsafe] [extern "C"] fn() [-> !]`
--> tests/riscv-rt/core_interrupt/fail_signatures.rs:2:1
|
2 | fn my_interrupt(code: usize) {}
| ^^

error: `#[core_interrupt]` function must have signature `[unsafe] fn() [-> !]`
error: `#[core_interrupt]` function must have signature `[unsafe] [extern "C"] fn() [-> !]`
--> tests/riscv-rt/core_interrupt/fail_signatures.rs:5:1
|
5 | fn my_other_interrupt() -> usize {}
| ^^

error: `#[core_interrupt]` function must have signature `[unsafe] fn() [-> !]`
error: `#[core_interrupt]` function must have signature `[unsafe] [extern "C"] fn() [-> !]`
--> tests/riscv-rt/core_interrupt/fail_signatures.rs:8:1
|
8 | async fn my_async_interrupt() {}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
error: `#[exception]` function must have signature `[unsafe] fn([&[mut] riscv_rt::TrapFrame]) [-> !]`
error: `#[exception]` function must have signature `[unsafe] [extern "C"] fn([&[mut] riscv_rt::TrapFrame]) [-> !]`
--> tests/riscv-rt/exception/fail_signatures.rs:2:1
|
2 | fn my_exception(code: usize) {}
| ^^

error: `#[exception]` function must have signature `[unsafe] fn([&[mut] riscv_rt::TrapFrame]) [-> !]`
error: `#[exception]` function must have signature `[unsafe] [extern "C"] fn([&[mut] riscv_rt::TrapFrame]) [-> !]`
--> tests/riscv-rt/exception/fail_signatures.rs:5:1
|
5 | fn my_other_exception(trap_frame: &riscv_rt::TrapFrame, code: usize) {}
| ^^

error: `#[exception]` function must have signature `[unsafe] fn([&[mut] riscv_rt::TrapFrame]) [-> !]`
error: `#[exception]` function must have signature `[unsafe] [extern "C"] fn([&[mut] riscv_rt::TrapFrame]) [-> !]`
--> tests/riscv-rt/exception/fail_signatures.rs:8:1
|
8 | async fn my_async_exception(trap_frame: &riscv_rt::TrapFrame, code: usize) {}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
error: `#[external_interrupt]` function must have signature `[unsafe] fn() [-> !]`
error: `#[external_interrupt]` function must have signature `[unsafe] [extern "C"] fn() [-> !]`
--> tests/riscv-rt/external_interrupt/fail_signatures.rs:31:1
|
31 | fn my_interrupt() -> usize {}
| ^^

error: `#[external_interrupt]` function must have signature `[unsafe] fn() [-> !]`
error: `#[external_interrupt]` function must have signature `[unsafe] [extern "C"] fn() [-> !]`
--> tests/riscv-rt/external_interrupt/fail_signatures.rs:34:1
|
34 | fn my_other_interrupt(code: usize) -> usize {}
| ^^

error: `#[external_interrupt]` function must have signature `[unsafe] fn() [-> !]`
error: `#[external_interrupt]` function must have signature `[unsafe] [extern "C"] fn() [-> !]`
--> tests/riscv-rt/external_interrupt/fail_signatures.rs:37:1
|
37 | async fn my_async_interrupt(code: usize) -> usize {}
Expand Down
Loading