blob: b5c2cd4702d93e17cf63e461ad285d05f635320a [file] [log] [blame]
//! 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();
}
}