#![allow(dead_code)]
extern crate libc;
extern crate num_cpus;
pub mod exec;
pub mod instrument;
pub mod task;
use std::env;
use std::ffi::CStr;
use std::mem;
use std::path::{Path, PathBuf};
use std::sync::{Arc, Once};
pub use crate::exec::{Parallel, TaskSystem};
pub use crate::instrument::{Instrument, SimpleInstrument};
pub use crate::task::ISPCTaskFn;
#[macro_export]
macro_rules! ispc_module {
($lib:ident) => {
include!(concat!(env!("ISPC_OUT_DIR"), "/", stringify!($lib), ".rs"));
};
}
pub struct PackagedModule {
path: Option<PathBuf>,
lib: String,
}
impl PackagedModule {
pub fn new(lib: &str) -> PackagedModule {
PackagedModule {
path: None,
lib: lib.to_owned(),
}
}
pub fn lib_path<P: AsRef<Path>>(&mut self, path: P) -> &mut PackagedModule {
self.path = Some(path.as_ref().to_path_buf());
self
}
pub fn link(&self) {
let path = self.get_lib_path();
let libfile = self.lib.clone() + &env::var("TARGET").unwrap();
let bindgen_file = self.lib.clone() + ".rs";
println!("cargo:rustc-link-lib=static={libfile}");
println!(
"cargo:rerun-if-changed={}",
path.join(get_lib_filename(&libfile)).display()
);
println!(
"cargo:rerun-if-changed={}",
path.join(bindgen_file).display()
);
println!("cargo:rustc-link-search=native={}", path.display());
println!("cargo:rustc-env=ISPC_OUT_DIR={}", path.display());
}
fn get_lib_path(&self) -> PathBuf {
let p = self
.path
.clone()
.unwrap_or_else(|| env::var_os("OUT_DIR").map(PathBuf::from).unwrap());
if p.is_relative() {
env::current_dir().unwrap().join(p)
} else {
p
}
}
}
fn get_lib_filename(libfile: &str) -> String {
if libfile.contains("windows") {
format!("{libfile}.lib")
} else {
format!("lib{libfile}.a")
}
}
static mut TASK_SYSTEM: Option<&'static dyn TaskSystem> = None;
static TASK_INIT: Once = Once::new();
static mut INSTRUMENT: Option<&'static dyn Instrument> = None;
static INSTRUMENT_INIT: Once = Once::new();
pub fn set_task_system<F: FnOnce() -> Arc<dyn TaskSystem>>(f: F) {
TASK_INIT.call_once(|| {
let task_sys = f();
unsafe {
let s = &*task_sys as *const (dyn TaskSystem + 'static);
mem::forget(task_sys);
TASK_SYSTEM = Some(&*s);
}
});
}
fn get_task_system() -> &'static dyn TaskSystem {
TASK_INIT.call_once(|| unsafe {
let task_sys = Parallel::new() as Arc<dyn TaskSystem>;
let s = &*task_sys as *const (dyn TaskSystem + 'static);
mem::forget(task_sys);
TASK_SYSTEM = Some(&*s);
});
unsafe { TASK_SYSTEM.unwrap() }
}
pub fn set_instrument<F: FnOnce() -> Arc<dyn Instrument>>(f: F) {
INSTRUMENT_INIT.call_once(|| {
let instrument = f();
unsafe {
let s = &*instrument as *const (dyn Instrument + 'static);
mem::forget(instrument);
INSTRUMENT = Some(&*s);
}
});
}
pub fn print_instrumenting_summary() {
get_instrument().print_summary();
}
fn get_instrument() -> &'static dyn Instrument {
INSTRUMENT_INIT.call_once(|| unsafe {
let instrument = Arc::new(SimpleInstrument) as Arc<dyn Instrument>;
let s = &*instrument as *const (dyn Instrument + 'static);
mem::forget(instrument);
INSTRUMENT = Some(&*s);
});
unsafe { INSTRUMENT.unwrap() }
}
#[allow(non_snake_case)]
#[doc(hidden)]
#[no_mangle]
pub unsafe extern "C" fn ISPCAlloc(
handle_ptr: *mut *mut libc::c_void,
size: i64,
align: i32,
) -> *mut libc::c_void {
get_task_system().alloc(handle_ptr, size, align)
}
#[allow(non_snake_case)]
#[doc(hidden)]
#[no_mangle]
pub unsafe extern "C" fn ISPCLaunch(
handle_ptr: *mut *mut libc::c_void,
f: *mut libc::c_void,
data: *mut libc::c_void,
count0: libc::c_int,
count1: libc::c_int,
count2: libc::c_int,
) {
let task_fn: ISPCTaskFn = mem::transmute(f);
get_task_system().launch(handle_ptr, task_fn, data, count0, count1, count2);
}
#[allow(non_snake_case)]
#[doc(hidden)]
#[no_mangle]
pub unsafe extern "C" fn ISPCSync(handle: *mut libc::c_void) {
get_task_system().sync(handle);
}
#[allow(non_snake_case)]
#[doc(hidden)]
#[no_mangle]
pub unsafe extern "C" fn ISPCInstrument(
cfile: *const libc::c_char,
cnote: *const libc::c_char,
line: libc::c_int,
mask: u64,
) {
let file_name = CStr::from_ptr(cfile);
let note = CStr::from_ptr(cnote);
let active_count = mask.count_ones();
get_instrument().instrument(file_name, note, line, mask, active_count);
}