neo_devpack_solidity/cli/cli_parts/cli_run/run.rs
1/// Stack budget for the compiler driver thread spawned by [`run`]. Keep in
2/// sync with `PARSE_THREAD_STACK_BYTES` in
3/// src/frontend/frontend_guarded_parse.rs so every stage shares one ceiling.
4const DRIVER_THREAD_STACK_BYTES: usize = 256 * 1024 * 1024;
5
6pub fn run() {
7 // The Solidity AST is deeply recursive. Parsing is guarded by
8 // `frontend::parse_solidity_guarded` (own worker thread, large stack)
9 // and the IR lowering walks are `stacker`-guarded, but other passes
10 // still recurse over the full tree on the calling thread's stack —
11 // e.g. the derive(Clone) walk in `analyse_all_sources` and the
12 // recursive `Drop` of the parse tree at scope exit. Run the whole
13 // driver on a worker thread with a large bounded stack so a deeply
14 // nested (but otherwise valid) source can't abort the process with a
15 // main-thread stack overflow.
16 let worker = std::thread::Builder::new()
17 .name("neo-solc-driver".to_string())
18 .stack_size(DRIVER_THREAD_STACK_BYTES)
19 .spawn(run_driver);
20
21 match worker {
22 Ok(handle) => {
23 if let Err(panic) = handle.join() {
24 std::panic::resume_unwind(panic);
25 }
26 }
27 // Spawning a thread only fails under extreme resource exhaustion;
28 // fall back to running on the current thread (pre-guard behavior)
29 // rather than refusing to compile.
30 Err(_) => run_driver(),
31 }
32}
33
34fn run_driver() {
35 let matches = build_matches();
36
37 if try_run_standard_json(&matches) {
38 return;
39 }
40
41 run_single_file(&matches);
42}