diff options
| author | Thomas Voss <mail@thomasvoss.com> | 2026-03-10 17:40:25 +0100 |
|---|---|---|
| committer | Thomas Voss <mail@thomasvoss.com> | 2026-03-10 17:40:25 +0100 |
| commit | 773b5a8349af9776a1f96bd37bcec9263dd79a91 (patch) | |
| tree | 7d2f5f01584d2a6592ff02c801563a8509dc792e /oryxc | |
| parent | 59b2e5bd0fd7cea5fc3f9c74241cf4fa08e99228 (diff) | |
Exit with the correct exit status
Diffstat (limited to 'oryxc')
| -rw-r--r-- | oryxc/src/compiler.rs | 93 |
1 files changed, 64 insertions, 29 deletions
diff --git a/oryxc/src/compiler.rs b/oryxc/src/compiler.rs index d934a29..a855584 100644 --- a/oryxc/src/compiler.rs +++ b/oryxc/src/compiler.rs @@ -94,11 +94,12 @@ pub enum JobType { scope: ScopeId, block: u32, }, - ResolveDefBind { - fdata: Arc<FileData>, - scope: ScopeId, - node: u32, }, + ResolveDefBind { + fdata: Arc<FileData>, + node: u32, + scope: ScopeId, + }, } pub struct Job { @@ -145,6 +146,14 @@ impl<'a> CompilerState<'a> { queue.push(job); self.wake_all(); } + + /// Signal a job completion by decrementing the job count. + /// + /// Returns the number of remaining jobs + #[inline(always)] + fn job_complete(&self) -> usize { + return self.njobs.fetch_sub(1, Ordering::Release) - 1; + } } /// Initialize compiler state and drive all source files through the @@ -214,20 +223,38 @@ where let workers = unsafe { workers.assume_init() }; let stealers = Arc::from(unsafe { stealers.assume_init() }); - let mut worker_threads = Box::new_uninit_slice(workers.len()); + let mut ok = true; thread::scope(|s| { + let mut handles = Box::new_uninit_slice(workers.len()); + let mut worker_threads = Box::new_uninit_slice(handles.len()); + for (i, w) in workers.into_iter().enumerate() { let stealers = Arc::clone(&stealers); let state = Arc::clone(&state); let arena = LocalArena::new(&state.global_arena); let handle = s.spawn(move || worker_loop(i, state, w, stealers)); worker_threads[i].write(handle.thread().clone()); + handles[i].write(handle); } let _ = state .worker_threads .set(unsafe { worker_threads.assume_init() }); state.wake_all(); + + for h in handles { + match unsafe { h.assume_init() }.join() { + Ok(thrd_ok) => { + if !thrd_ok { + ok = false; + } + }, + Err(_) => ok = false, + } + } }); + if !ok { + process::exit(1); + } } /// Steal and execute jobs until all work is complete. @@ -236,7 +263,8 @@ fn worker_loop( c_state: Arc<CompilerState>, queue: Worker<Job>, stealers: Arc<[Stealer<Job>]>, -) { +) -> bool { + let mut ok = true; let arena = LocalArena::new(&c_state.global_arena); loop { @@ -246,19 +274,21 @@ fn worker_loop( let n = c_state.njobs.load(Ordering::Acquire); if n == 0 { c_state.wake_all(); - return; + return ok; } thread::park(); continue; }; - match job.kind { - JobType::Lex { file, fdata } => { - let tokens = - lexer::tokenize(&fdata.buffer).unwrap_or_else(|e| { + let result = match job.kind { + JobType::Lex { file, fdata } => 'blk: { + let tokens = match lexer::tokenize(&fdata.buffer) { + Ok(xs) => xs, + Err(e) => { emit_errors(&fdata, iter::once(e)); - process::exit(1) - }); + break 'blk false; + }, + }; if c_state.flags.debug_lexer { let mut handle = io::stderr().lock(); @@ -272,16 +302,17 @@ fn worker_loop( &queue, c_state.job_new(JobType::Parse { file, fdata }), ); + true }, - JobType::Parse { file, fdata } => { - let (ast, extra_data) = parser::parse( - fdata.tokens.get().unwrap(), - ) - .unwrap_or_else(|errs| { - emit_errors(&fdata, errs); - process::exit(1) - }); + JobType::Parse { file, fdata } => 'blk: { + let ast = match parser::parse(fdata.tokens.get().unwrap()) { + Ok(ast) => ast, + Err(errs) => { + emit_errors(&fdata, errs); + break 'blk false; + }, + }; if c_state.flags.debug_parser { let mut handle = io::stderr().lock(); @@ -301,6 +332,7 @@ fn worker_loop( block: root, }), ); + true }, JobType::FindSymbolsInScope { @@ -361,10 +393,18 @@ fn worker_loop( ); } + let ok = errors.is_empty(); emit_errors(&fdata, errors); + ok }, - JobType::ResolveDefBind { fdata, scope, node } => {}, + JobType::ResolveDefBind { fdata, node, scope } => { + todo!("resolving is yet to be implemented"); + true + }, + }; + if !result { + ok = false; } if let Some((_, deps)) = c_state.deps.remove(&job.id) { @@ -373,14 +413,9 @@ fn worker_loop( } } - if c_state.njobs.fetch_sub(1, Ordering::Release) == 1 { - // njobs is 0; wake all threads so they can observe the termination - // condition and exit. + if c_state.job_complete() == 0 { c_state.wake_all(); - - // break here to avoid unnecessary steal attempts after work is - // done. - break; + return ok; } } } |