1#![allow(dead_code)]
12
13extern crate libc;
14extern crate num_cpus;
15
16pub mod exec;
17pub mod instrument;
18pub mod task;
19
20use std::env;
21use std::ffi::CStr;
22use std::mem;
23use std::path::{Path, PathBuf};
24use std::sync::{Arc, Once};
25
26pub use crate::exec::{Parallel, TaskSystem};
27pub use crate::instrument::{Instrument, SimpleInstrument};
28pub use crate::task::ISPCTaskFn;
29
30#[macro_export]
46macro_rules! ispc_module {
47 ($lib:ident) => {
48 include!(concat!(env!("ISPC_OUT_DIR"), "/", stringify!($lib), ".rs"));
49 };
50}
51
52pub struct PackagedModule {
56 path: Option<PathBuf>,
57 lib: String,
58}
59
60impl PackagedModule {
61 pub fn new(lib: &str) -> PackagedModule {
66 PackagedModule {
67 path: None,
68 lib: lib.to_owned(),
69 }
70 }
71 pub fn lib_path<P: AsRef<Path>>(&mut self, path: P) -> &mut PackagedModule {
73 self.path = Some(path.as_ref().to_path_buf());
74 self
75 }
76 pub fn link(&self) {
78 let path = self.get_lib_path();
79 let libfile = self.lib.clone() + &env::var("TARGET").unwrap();
80 let bindgen_file = self.lib.clone() + ".rs";
81
82 println!("cargo:rustc-link-lib=static={libfile}");
83 println!(
84 "cargo:rerun-if-changed={}",
85 path.join(get_lib_filename(&libfile)).display()
86 );
87 println!(
88 "cargo:rerun-if-changed={}",
89 path.join(bindgen_file).display()
90 );
91 println!("cargo:rustc-link-search=native={}", path.display());
92 println!("cargo:rustc-env=ISPC_OUT_DIR={}", path.display());
93 }
94 fn get_lib_path(&self) -> PathBuf {
97 let p = self
98 .path
99 .clone()
100 .unwrap_or_else(|| env::var_os("OUT_DIR").map(PathBuf::from).unwrap());
101 if p.is_relative() {
102 env::current_dir().unwrap().join(p)
103 } else {
104 p
105 }
106 }
107}
108
109fn get_lib_filename(libfile: &str) -> String {
110 if libfile.contains("windows") {
111 format!("{libfile}.lib")
112 } else {
113 format!("lib{libfile}.a")
114 }
115}
116
117static mut TASK_SYSTEM: Option<&'static dyn TaskSystem> = None;
118static TASK_INIT: Once = Once::new();
119
120static mut INSTRUMENT: Option<&'static dyn Instrument> = None;
121static INSTRUMENT_INIT: Once = Once::new();
122
123pub fn set_task_system<F: FnOnce() -> Arc<dyn TaskSystem>>(f: F) {
132 TASK_INIT.call_once(|| {
133 let task_sys = f();
134 unsafe {
135 let s = &*task_sys as *const (dyn TaskSystem + 'static);
136 mem::forget(task_sys);
137 TASK_SYSTEM = Some(&*s);
138 }
139 });
140}
141
142fn get_task_system() -> &'static dyn TaskSystem {
143 TASK_INIT.call_once(|| unsafe {
147 let task_sys = Parallel::new() as Arc<dyn TaskSystem>;
148 let s = &*task_sys as *const (dyn TaskSystem + 'static);
149 mem::forget(task_sys);
150 TASK_SYSTEM = Some(&*s);
151 });
152 unsafe { TASK_SYSTEM.unwrap() }
153}
154
155pub fn set_instrument<F: FnOnce() -> Arc<dyn Instrument>>(f: F) {
160 INSTRUMENT_INIT.call_once(|| {
161 let instrument = f();
162 unsafe {
163 let s = &*instrument as *const (dyn Instrument + 'static);
164 mem::forget(instrument);
165 INSTRUMENT = Some(&*s);
166 }
167 });
168}
169
170pub fn print_instrumenting_summary() {
174 get_instrument().print_summary();
175}
176
177fn get_instrument() -> &'static dyn Instrument {
178 INSTRUMENT_INIT.call_once(|| unsafe {
180 let instrument = Arc::new(SimpleInstrument) as Arc<dyn Instrument>;
181 let s = &*instrument as *const (dyn Instrument + 'static);
182 mem::forget(instrument);
183 INSTRUMENT = Some(&*s);
184 });
185 unsafe { INSTRUMENT.unwrap() }
186}
187
188#[allow(non_snake_case)]
189#[doc(hidden)]
190#[no_mangle]
191pub unsafe extern "C" fn ISPCAlloc(
192 handle_ptr: *mut *mut libc::c_void,
193 size: i64,
194 align: i32,
195) -> *mut libc::c_void {
196 get_task_system().alloc(handle_ptr, size, align)
197}
198
199#[allow(non_snake_case)]
200#[doc(hidden)]
201#[no_mangle]
202pub unsafe extern "C" fn ISPCLaunch(
203 handle_ptr: *mut *mut libc::c_void,
204 f: *mut libc::c_void,
205 data: *mut libc::c_void,
206 count0: libc::c_int,
207 count1: libc::c_int,
208 count2: libc::c_int,
209) {
210 let task_fn: ISPCTaskFn = mem::transmute(f);
211 get_task_system().launch(handle_ptr, task_fn, data, count0, count1, count2);
212}
213
214#[allow(non_snake_case)]
215#[doc(hidden)]
216#[no_mangle]
217pub unsafe extern "C" fn ISPCSync(handle: *mut libc::c_void) {
218 get_task_system().sync(handle);
219}
220
221#[allow(non_snake_case)]
222#[doc(hidden)]
223#[no_mangle]
224pub unsafe extern "C" fn ISPCInstrument(
225 cfile: *const libc::c_char,
226 cnote: *const libc::c_char,
227 line: libc::c_int,
228 mask: u64,
229) {
230 let file_name = CStr::from_ptr(cfile);
231 let note = CStr::from_ptr(cnote);
232 let active_count = mask.count_ones();
233 get_instrument().instrument(file_name, note, line, mask, active_count);
234}