ckb_std/
entry.rs

1/// Define program entry point (`_start` function) and lang items (panic handler, etc.).
2///
3/// # Examples
4///
5/// Simple main function:
6///
7/// ```
8/// entry!(main)
9///
10/// fn main() -> i8 {
11///    0
12/// }
13/// ```
14#[macro_export]
15macro_rules! entry {
16    ($main:path) => {
17        extern crate alloc;
18
19        #[cfg(not(target_arch = "riscv64"))]
20        #[unsafe(no_mangle)]
21        pub extern "C" fn _start() -> ! {
22            panic!("ckb_std::entry is only valid for riscv64 target")
23        }
24
25        #[unsafe(no_mangle)]
26        unsafe extern "C" fn __ckb_std_main(
27            argc: core::ffi::c_int,
28            // Arg is the same as *const c_char ABI wise.
29            argv: *const $crate::env::Arg,
30        ) -> i8 {
31            let argv = core::slice::from_raw_parts(argv, argc as usize);
32            $crate::env::set_argv(argv);
33            $main()
34        }
35
36        // Use global_asm so the compiler won't insert function prologue in _start.
37        #[cfg(target_arch = "riscv64")]
38        core::arch::global_asm!(
39            ".global _start",
40            "_start:",
41            // Argc.
42            "lw a0, 0(sp)",
43            // Argv.
44            "addi a1, sp, 8",
45            // Envp.
46            "li a2, 0",
47            "call __ckb_std_main",
48            // Exit.
49            "li a7, 93",
50            "ecall",
51        );
52
53        #[cfg(target_arch = "riscv64")]
54        #[panic_handler]
55        fn panic_handler(panic_info: &core::panic::PanicInfo) -> ! {
56            $crate::debug!("{}", panic_info);
57            $crate::syscalls::exit(unsafe { $crate::asserts::__PANIC_EXIT_CODE })
58        }
59    };
60}
61
62#[cfg(feature = "native-simulator")]
63#[macro_export]
64macro_rules! entry_simulator {
65    ($main:path) => {
66        extern crate alloc;
67
68        #[unsafe(no_mangle)]
69        unsafe extern "C" fn __ckb_std_main(
70            argc: core::ffi::c_int,
71            // Arg is the same as *const c_char ABI wise.
72            argv: *const $crate::env::Arg,
73        ) -> i8 {
74            let argv = if argc == 0 {
75                &[]
76            } else {
77                core::slice::from_raw_parts(argv, argc as usize)
78            };
79            $crate::env::set_argv(argv);
80            $main()
81        }
82
83        #[unsafe(no_mangle)]
84        unsafe extern "C" fn __set_script_info(
85            ptr: *mut core::ffi::c_void,
86            tx_ctx_id: u64,
87            proc_ctx_id: u64,
88        ) {
89            ckb_std::set_script_info(ptr, tx_ctx_id, proc_ctx_id)
90        }
91    };
92}