1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59
/// Define program entry point (`_start` function) and lang items (panic handler, etc.).
///
/// # Examples
///
/// Simple main function:
///
/// ```
/// entry!(main)
///
/// fn main() -> i8 {
/// 0
/// }
/// ```
#[macro_export]
macro_rules! entry {
($main:path) => {
extern crate alloc;
#[cfg(not(target_arch = "riscv64"))]
#[no_mangle]
pub extern "C" fn _start() -> ! {
panic!("ckb_std::entry is only valid for riscv64 target")
}
#[no_mangle]
unsafe extern "C" fn __ckb_std_main(
argc: core::ffi::c_int,
// Arg is the same as *const c_char ABI wise.
argv: *const $crate::env::Arg,
) -> i8 {
let argv = core::slice::from_raw_parts(argv, argc as usize);
$crate::env::set_argv(argv);
$main()
}
// Use global_asm so the compiler won't insert function prologue in _start.
#[cfg(target_arch = "riscv64")]
core::arch::global_asm!(
".global _start",
"_start:",
// Argc.
"lw a0, 0(sp)",
// Argv.
"addi a1, sp, 8",
// Envp.
"li a2, 0",
"call __ckb_std_main",
// Exit.
"li a7, 93",
"ecall",
);
#[panic_handler]
fn panic_handler(panic_info: &core::panic::PanicInfo) -> ! {
$crate::debug!("{}", panic_info);
$crate::syscalls::exit(-1)
}
};
}