From 7d42170c8625de0fe44b98f47e8b9a603a9de794 Mon Sep 17 00:00:00 2001 From: Thomas Voss Date: Tue, 24 Feb 2026 11:08:42 +0100 Subject: Genesis commit --- oryxc/src/compiler.rs | 136 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 136 insertions(+) create mode 100644 oryxc/src/compiler.rs (limited to 'oryxc/src/compiler.rs') diff --git a/oryxc/src/compiler.rs b/oryxc/src/compiler.rs new file mode 100644 index 0000000..05e275f --- /dev/null +++ b/oryxc/src/compiler.rs @@ -0,0 +1,136 @@ +use std::ffi::OsString; +use std::iter::IntoIterator; +use std::sync::Arc; +use std::sync::atomic::{ + AtomicUsize, + Ordering, +}; +use std::vec::Vec; +use std::{ + panic, + thread, +}; + +use crossbeam_deque::{ + Injector, + Steal, + Stealer, + Worker, +}; +use dashmap::DashMap; + +use crate::Flags; + +#[derive(Clone, Copy, Eq, Hash, PartialEq)] +pub struct FileId(u32); + +pub struct FileData { + name: OsString, +} + +pub enum Job { + LexAndParse { file: FileId }, + TypeCheck { file: FileId }, +} + +pub struct CompilerState { + pub files: DashMap, + pub globalq: Injector, + pub njobs: AtomicUsize, + pub flags: Flags, +} + +pub fn start(paths: T, flags: Flags) +where + T: IntoIterator, +{ + let state = Arc::new(CompilerState { + files: DashMap::new(), + globalq: Injector::new(), + njobs: AtomicUsize::new(0), + flags, + }); + for (i, path) in paths.into_iter().enumerate() { + let id = FileId(i as u32); + state.files.insert(id, FileData { name: path.clone() }); + state.njobs.fetch_add(1, Ordering::SeqCst); + state.globalq.push(Job::LexAndParse { file: id }); + } + + let mut workers = Vec::with_capacity(flags.threads); + let mut stealers = Vec::with_capacity(flags.threads); + for _ in 0..flags.threads { + let w = Worker::new_fifo(); + stealers.push(w.stealer()); + workers.push(w); + } + + let mut threads = Vec::with_capacity(flags.threads); + let stealer_view: Arc<[_]> = Arc::from(stealers); + + for (id, w) in workers.into_iter().enumerate() { + let stealer_view = Arc::clone(&stealer_view); + let state = Arc::clone(&state); + threads.push(thread::spawn(move || { + worker_loop(id, w, stealer_view, state); + })); + } + + for t in threads { + t.join().unwrap_or_else(|e| panic::resume_unwind(e)); + } +} + +fn worker_loop( + id: usize, + queue: Worker, + stealers: Arc<[Stealer]>, + state: Arc, +) { + loop { + if state.njobs.load(Ordering::SeqCst) == 0 { + break; + } + + let job = find_task(&queue, &state.globalq, &stealers); + if let Some(job) = job { + match job { + LexAndParse { file } => {}, + } + + state.njobs.fetch_sub(1, Ordering::SeqCst); + } else { + thread::yield_now(); + } + } +} + +fn find_task( + localq: &Worker, + globalq: &Injector, + stealers: &Arc<[Stealer]>, +) -> Option { + if let Some(job) = localq.pop() { + return Some(job); + } + + loop { + match globalq.steal_batch_and_pop(localq) { + Steal::Success(job) => return Some(job), + Steal::Empty => break, + Steal::Retry => continue, + } + } + + for s in stealers.iter() { + loop { + match s.steal_batch_and_pop(localq) { + Steal::Success(job) => return Some(job), + Steal::Empty => break, + Steal::Retry => continue, + } + } + } + + return None; +} -- cgit v1.2.3