| //! Lang item required to make the normal `main` work in applications |
| //! |
| //! This is how the `start` lang item works: |
| //! When `rustc` compiles a binary crate, it creates a `main` function that looks |
| //! like this: |
| //! |
| //! ``` |
| //! #[export_name = "main"] |
| //! pub extern "C" fn rustc_main(argc: isize, argv: *const *const u8) -> isize { |
| //! start(main, argc, argv) |
| //! } |
| //! ``` |
| //! |
| //! Where `start` is this function and `main` is the binary crate's `main` |
| //! function. |
| //! |
| //! The final piece is that the entry point of our program, _start, has to call |
| //! `rustc_main`. That's covered by the `_start` function in the root of this |
| //! crate. |
| |
| use crate::syscalls; |
| |
| #[lang = "start"] |
| extern "C" fn start<T>(main: fn() -> T, _argc: isize, _argv: *const *const u8) -> bool |
| where |
| T: Termination, |
| { |
| main().check_result(); |
| true // Need to return anything sized. Otherwise, a linker error pops up. (See https://github.com/tock/libtock-rs/issues/138) |
| } |
| |
| #[lang = "termination"] |
| pub trait Termination { |
| fn check_result(self); |
| } |
| |
| impl Termination for () { |
| fn check_result(self) {} |
| } |
| |
| impl<S, T> Termination for Result<S, T> { |
| fn check_result(self) { |
| if self.is_err() { |
| unsafe { report_panic() }; |
| } |
| } |
| } |
| |
| #[cfg(not(feature = "custom_panic_handler"))] |
| #[panic_handler] |
| unsafe fn panic_handler(_info: &core::panic::PanicInfo) -> ! { |
| report_panic() |
| } |
| |
| unsafe fn report_panic() -> ! { |
| // Signal a panic using the LowLevelDebug capsule (if available). |
| let _ = syscalls::command1_insecure(8, 1, 1); |
| |
| loop { |
| syscalls::raw::yieldk(); |
| } |
| } |