From 90fa8545255a59af5db64ae6e41d4fb3176542ae Mon Sep 17 00:00:00 2001 From: DianQK Date: Sun, 17 Dec 2023 18:54:25 +0800 Subject: [PATCH 1/4] Add the `weak-intrinsics` feature to compiler_builtins. --- rp2040-hal/Cargo.toml | 1 + rp2040-hal/src/lib.rs | 1 + 2 files changed, 2 insertions(+) diff --git a/rp2040-hal/Cargo.toml b/rp2040-hal/Cargo.toml index 293120799..aad5773dc 100644 --- a/rp2040-hal/Cargo.toml +++ b/rp2040-hal/Cargo.toml @@ -16,6 +16,7 @@ targets = ["thumbv6m-none-eabi"] # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +compiler_builtins = { version = "0.1.104", features = ["weak-intrinsics"] } cortex-m = "0.7.2" embedded-hal = { version = "0.2.5", features = ["unproven"] } eh1_0_alpha = { package = "embedded-hal", version = "=1.0.0-rc.1", optional = true } diff --git a/rp2040-hal/src/lib.rs b/rp2040-hal/src/lib.rs index 3f14385dc..23fcd3130 100644 --- a/rp2040-hal/src/lib.rs +++ b/rp2040-hal/src/lib.rs @@ -94,6 +94,7 @@ pub use sio::Sio; pub use spi::Spi; pub use timer::Timer; pub use watchdog::Watchdog; +extern crate compiler_builtins; // Re-export crates used in rp2040-hal's public API pub extern crate fugit; From 99a0ebd942039d335eb529a50238740bbfb1f64a Mon Sep 17 00:00:00 2001 From: DianQK Date: Sun, 17 Dec 2023 18:54:46 +0800 Subject: [PATCH 2/4] Add intrinsics support for the optional return value. --- rp2040-hal/src/intrinsics.rs | 60 ++++++++++++++++++------------------ 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/rp2040-hal/src/intrinsics.rs b/rp2040-hal/src/intrinsics.rs index ca77da106..656241540 100644 --- a/rp2040-hal/src/intrinsics.rs +++ b/rp2040-hal/src/intrinsics.rs @@ -1,46 +1,46 @@ /// Generate a series of aliases for an intrinsic function. macro_rules! intrinsics_aliases { ( - extern $abi:tt fn $name:ident( $($argname:ident: $ty:ty),* ) -> $ret:ty, + extern $abi:tt fn $name:ident( $($argname:ident: $ty:ty),* ) $(-> $ret:ty)?, ) => {}; ( - unsafe extern $abi:tt fn $name:ident( $($argname:ident: $ty:ty),* ) -> $ret:ty, + unsafe extern $abi:tt fn $name:ident( $($argname:ident: $ty:ty),* ) $(-> $ret:ty)?, ) => {}; ( - extern $abi:tt fn $name:ident( $($argname:ident: $ty:ty),* ) -> $ret:ty, + extern $abi:tt fn $name:ident( $($argname:ident: $ty:ty),* ) $(-> $ret:ty)?, $alias:ident $($rest:ident)* ) => { #[cfg(all(target_arch = "arm", not(feature = "disable-intrinsics")))] mod $alias { #[no_mangle] - pub extern $abi fn $alias( $($argname: $ty),* ) -> $ret { + pub extern $abi fn $alias( $($argname: $ty),* ) $(-> $ret)? { super::$name($($argname),*) } } intrinsics_aliases! { - extern $abi fn $name( $($argname: $ty),* ) -> $ret, + extern $abi fn $name( $($argname: $ty),* ) $(-> $ret)?, $($rest)* } }; ( - unsafe extern $abi:tt fn $name:ident( $($argname:ident: $ty:ty),* ) -> $ret:ty, + unsafe extern $abi:tt fn $name:ident( $($argname:ident: $ty:ty),* ) $(-> $ret:ty)?, $alias:ident $($rest:ident)* ) => { #[cfg(all(target_arch = "arm", not(feature = "disable-intrinsics")))] mod $alias { #[no_mangle] - unsafe extern $abi fn $alias( $($argname: $ty),* ) -> $ret { + unsafe extern $abi fn $alias( $($argname: $ty),* ) $(-> $ret)? { super::$name($($argname),*) } } intrinsics_aliases! { - unsafe extern $abi fn $name( $($argname: $ty),* ) -> $ret, + unsafe extern $abi fn $name( $($argname: $ty),* ) $(-> $ret)?, $($rest)* } }; @@ -88,7 +88,7 @@ macro_rules! intrinsics { ( #[slower_than_default] $(#[$($attr:tt)*])* - extern $abi:tt fn $name:ident( $($argname:ident: $ty:ty),* ) -> $ret:ty { + extern $abi:tt fn $name:ident( $($argname:ident: $ty:ty),* ) $(-> $ret:ty)? { $($body:tt)* } @@ -97,7 +97,7 @@ macro_rules! intrinsics { // Not exported, but defined so the actual implementation is // considered used #[allow(dead_code)] - fn $name( $($argname: $ty),* ) -> $ret { + fn $name( $($argname: $ty),* ) $(-> $ret)? { $($body)* } @@ -107,7 +107,7 @@ macro_rules! intrinsics { ( #[bootrom_v2] $(#[$($attr:tt)*])* - extern $abi:tt fn $name:ident( $($argname:ident: $ty:ty),* ) -> $ret:ty { + extern $abi:tt fn $name:ident( $($argname:ident: $ty:ty),* ) $(-> $ret:ty)? { $($body:tt)* } @@ -117,14 +117,14 @@ macro_rules! intrinsics { // considered used #[cfg(not(feature = "rom-v2-intrinsics"))] #[allow(dead_code)] - fn $name( $($argname: $ty),* ) -> $ret { + fn $name( $($argname: $ty),* ) $(-> $ret)? { $($body)* } #[cfg(feature = "rom-v2-intrinsics")] intrinsics! { $(#[$($attr)*])* - extern $abi fn $name( $($argname: $ty),* ) -> $ret { + extern $abi fn $name( $($argname: $ty),* ) $(-> $ret)? { $($body)* } } @@ -135,7 +135,7 @@ macro_rules! intrinsics { ( #[alias = $($alias:ident),*] $(#[$($attr:tt)*])* - extern $abi:tt fn $name:ident( $($argname:ident: $ty:ty),* ) -> $ret:ty { + extern $abi:tt fn $name:ident( $($argname:ident: $ty:ty),* ) $(-> $ret:ty)? { $($body:tt)* } @@ -143,13 +143,13 @@ macro_rules! intrinsics { ) => { intrinsics! { $(#[$($attr)*])* - extern $abi fn $name( $($argname: $ty),* ) -> $ret { + extern $abi fn $name( $($argname: $ty),* ) $(-> $ret)? { $($body)* } } intrinsics_aliases! { - extern $abi fn $name( $($argname: $ty),* ) -> $ret, + extern $abi fn $name( $($argname: $ty),* ) $(-> $ret)?, $($alias) * } @@ -159,7 +159,7 @@ macro_rules! intrinsics { ( #[alias = $($alias:ident),*] $(#[$($attr:tt)*])* - unsafe extern $abi:tt fn $name:ident( $($argname:ident: $ty:ty),* ) -> $ret:ty { + unsafe extern $abi:tt fn $name:ident( $($argname:ident: $ty:ty),* ) $(-> $ret:ty)? { $($body:tt)* } @@ -167,13 +167,13 @@ macro_rules! intrinsics { ) => { intrinsics! { $(#[$($attr)*])* - unsafe extern $abi fn $name( $($argname: $ty),* ) -> $ret { + unsafe extern $abi fn $name( $($argname: $ty),* ) $(-> $ret)? { $($body)* } } intrinsics_aliases! { - unsafe extern $abi fn $name( $($argname: $ty),* ) -> $ret, + unsafe extern $abi fn $name( $($argname: $ty),* ) $(-> $ret)?, $($alias) * } @@ -183,7 +183,7 @@ macro_rules! intrinsics { ( #[aeabi = $($alias:ident),*] $(#[$($attr:tt)*])* - extern $abi:tt fn $name:ident( $($argname:ident: $ty:ty),* ) -> $ret:ty { + extern $abi:tt fn $name:ident( $($argname:ident: $ty:ty),* ) $(-> $ret:ty)? { $($body:tt)* } @@ -191,13 +191,13 @@ macro_rules! intrinsics { ) => { intrinsics! { $(#[$($attr)*])* - extern $abi fn $name( $($argname: $ty),* ) -> $ret { + extern $abi fn $name( $($argname: $ty),* ) $(-> $ret)? { $($body)* } } intrinsics_aliases! { - extern "aapcs" fn $name( $($argname: $ty),* ) -> $ret, + extern "aapcs" fn $name( $($argname: $ty),* ) $(-> $ret)?, $($alias) * } @@ -206,7 +206,7 @@ macro_rules! intrinsics { ( $(#[$($attr:tt)*])* - extern $abi:tt fn $name:ident( $($argname:ident: $ty:ty),* ) -> $ret:ty { + extern $abi:tt fn $name:ident( $($argname:ident: $ty:ty),* ) $(-> $ret:ty)? { $($body:tt)* } @@ -214,7 +214,7 @@ macro_rules! intrinsics { ) => { #[cfg(all(target_arch = "arm", not(feature = "disable-intrinsics")))] $(#[$($attr)*])* - extern $abi fn $name( $($argname: $ty),* ) -> $ret { + extern $abi fn $name( $($argname: $ty),* ) $(-> $ret)? { $($body)* } @@ -222,7 +222,7 @@ macro_rules! intrinsics { mod $name { #[no_mangle] $(#[$($attr)*])* - pub extern $abi fn $name( $($argname: $ty),* ) -> $ret { + pub extern $abi fn $name( $($argname: $ty),* ) $(-> $ret)? { super::$name($($argname),*) } } @@ -231,7 +231,7 @@ macro_rules! intrinsics { // considered used #[cfg(not(all(target_arch = "arm", not(feature = "disable-intrinsics"))))] #[allow(dead_code)] - fn $name( $($argname: $ty),* ) -> $ret { + fn $name( $($argname: $ty),* ) $(-> $ret)? { $($body)* } @@ -240,7 +240,7 @@ macro_rules! intrinsics { ( $(#[$($attr:tt)*])* - unsafe extern $abi:tt fn $name:ident( $($argname:ident: $ty:ty),* ) -> $ret:ty { + unsafe extern $abi:tt fn $name:ident( $($argname:ident: $ty:ty),* ) $(-> $ret:ty)? { $($body:tt)* } @@ -248,7 +248,7 @@ macro_rules! intrinsics { ) => { #[cfg(all(target_arch = "arm", not(feature = "disable-intrinsics")))] $(#[$($attr)*])* - unsafe extern $abi fn $name( $($argname: $ty),* ) -> $ret { + unsafe extern $abi fn $name( $($argname: $ty),* ) $(-> $ret)? { $($body)* } @@ -256,7 +256,7 @@ macro_rules! intrinsics { mod $name { #[no_mangle] $(#[$($attr)*])* - pub unsafe extern $abi fn $name( $($argname: $ty),* ) -> $ret { + pub unsafe extern $abi fn $name( $($argname: $ty),* ) $(-> $ret)? { super::$name($($argname),*) } } @@ -265,7 +265,7 @@ macro_rules! intrinsics { // considered used #[cfg(not(all(target_arch = "arm", not(feature = "disable-intrinsics"))))] #[allow(dead_code)] - unsafe fn $name( $($argname: $ty),* ) -> $ret { + unsafe fn $name( $($argname: $ty),* ) $(-> $ret)? { $($body)* } From a2159881bd0c59701e6a2f46198d9f9809183d82 Mon Sep 17 00:00:00 2001 From: DianQK Date: Sun, 17 Dec 2023 20:22:55 +0800 Subject: [PATCH 3/4] Add the `naked` attribute of intrinsics --- rp2040-hal/src/intrinsics.rs | 23 +++++++++++++++++++++++ rp2040-hal/src/lib.rs | 1 + 2 files changed, 24 insertions(+) diff --git a/rp2040-hal/src/intrinsics.rs b/rp2040-hal/src/intrinsics.rs index 656241540..89ff1a43b 100644 --- a/rp2040-hal/src/intrinsics.rs +++ b/rp2040-hal/src/intrinsics.rs @@ -238,6 +238,29 @@ macro_rules! intrinsics { intrinsics!($($rest)*); }; + // Naked functions are special: we can't generate wrappers for them since + // they use a custom calling convention. + ( + #[naked] + $(#[$($attr:tt)*])* + unsafe extern $abi:tt fn $name:ident( $($argname:ident: $ty:ty),* ) $(-> $ret:ty)? { + $($body:tt)* + } + + $($rest:tt)* + ) => ( + mod $name { + #[naked] + $(#[$($attr)*])* + #[no_mangle] + pub unsafe extern $abi fn $name( $($argname: $ty),* ) $(-> $ret)? { + $($body)* + } + } + + intrinsics!($($rest)*); + ); + ( $(#[$($attr:tt)*])* unsafe extern $abi:tt fn $name:ident( $($argname:ident: $ty:ty),* ) $(-> $ret:ty)? { diff --git a/rp2040-hal/src/lib.rs b/rp2040-hal/src/lib.rs index 23fcd3130..fbb0bb894 100644 --- a/rp2040-hal/src/lib.rs +++ b/rp2040-hal/src/lib.rs @@ -37,6 +37,7 @@ #![warn(missing_docs)] #![no_std] +#![feature(naked_functions)] #[doc(hidden)] pub use paste; From 36244e6d15018d0c150b73b309b1f67cef1aa2cd Mon Sep 17 00:00:00 2001 From: DianQK Date: Sun, 17 Dec 2023 20:23:53 +0800 Subject: [PATCH 4/4] Change `division_function` to use the `naked` function Solve the issue of not recognizing builtin functions under LTO. --- rp2040-hal/src/sio.rs | 39 +++++++++++++++++++++------------------ 1 file changed, 21 insertions(+), 18 deletions(-) diff --git a/rp2040-hal/src/sio.rs b/rp2040-hal/src/sio.rs index ead75c858..c5df6ea43 100644 --- a/rp2040-hal/src/sio.rs +++ b/rp2040-hal/src/sio.rs @@ -278,29 +278,32 @@ core::arch::global_asm!( macro_rules! division_function { ( - $name:ident $($intrinsic:ident)* ( $argty:ty ) { + $name:ident $intrinsic:ident $intrinsic_alias:ident ( $argty:ty ) { $($begin:literal),+ } ) => { #[cfg(all(target_arch = "arm", not(feature = "disable-intrinsics")))] - core::arch::global_asm!( - // Mangle the name slightly, since this is a global symbol. - concat!(".global _rphal_", stringify!($name)), - concat!(".type _rphal_", stringify!($name), ", %function"), - ".align 2", - concat!("_rphal_", stringify!($name), ":"), - $( - concat!(".global ", stringify!($intrinsic)), - concat!(".type ", stringify!($intrinsic), ", %function"), - concat!(stringify!($intrinsic), ":"), - )* - - "hwdivider_head", - $($begin),+ , - "hwdivider_tail", - ); + intrinsics! { + #[naked] + unsafe extern "C" fn $intrinsic() { + core::arch::asm!( + "hwdivider_head", + $($begin),+ , + "hwdivider_tail", + options(noreturn) + ); + } + #[naked] + unsafe extern "C" fn $intrinsic_alias() { + core::arch::asm!( + "hwdivider_head", + $($begin),+ , + "hwdivider_tail", + options(noreturn) + ); + } + } - #[cfg(all(target_arch = "arm", feature = "disable-intrinsics"))] core::arch::global_asm!( // Mangle the name slightly, since this is a global symbol. concat!(".global _rphal_", stringify!($name)),