aboutsummaryrefslogtreecommitdiffhomepage
path: root/zluda_dump/src/side_by_side.rs
blob: 11789cad4f5ef10adc3af32c38057225ebbdd5b6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
use cuda_base::cuda_function_declarations;
use std::ffi::CStr;
use std::mem;
use std::ptr;
use std::ptr::NonNull;
use std::{marker::PhantomData, os::raw::c_void};

use crate::os;

struct DynamicFn<T> {
    pointer: usize,
    _marker: PhantomData<T>,
}

impl<T> Default for DynamicFn<T> {
    fn default() -> Self {
        DynamicFn {
            pointer: 0,
            _marker: PhantomData,
        }
    }
}

impl<T> DynamicFn<T> {
    unsafe fn get(&mut self, lib: *mut c_void, name: &[u8]) -> Option<T> {
        match self.pointer {
            0 => {
                let addr = os::get_proc_address(lib, CStr::from_bytes_with_nul_unchecked(name));
                if addr == ptr::null_mut() {
                    self.pointer = 1;
                    return None;
                } else {
                    self.pointer = addr as _;
                }
            }
            1 => return None,
            _ => {}
        }
        Some(mem::transmute_copy(&self.pointer))
    }
}

pub(crate) struct CudaDynamicFns {
    lib_handle: NonNull<::std::ffi::c_void>,
    fn_table: CudaFnTable,
}

impl CudaDynamicFns {
    pub(crate) unsafe fn load_library(path: &str) -> Option<Self> {
        let lib_handle = NonNull::new(os::load_library(path));
        lib_handle.map(|lib_handle| CudaDynamicFns {
            lib_handle,
            fn_table: CudaFnTable::default(),
        })
    }
}

macro_rules! emit_cuda_fn_table {
    ($($abi:literal fn $fn_name:ident( $($arg_id:ident : $arg_type:ty),* ) -> $ret_type:path;)*) => {
        #[derive(Default)]
        #[allow(improper_ctypes)]
        #[allow(improper_ctypes_definitions)]
        struct CudaFnTable {
            $($fn_name: DynamicFn<extern $abi fn ( $($arg_id : $arg_type),* ) -> $ret_type>),*
        }

        impl CudaDynamicFns {
            $(
                #[allow(dead_code)]
                pub(crate) fn $fn_name(&mut self, $($arg_id : $arg_type),*) -> Option<$ret_type> {
                    let func = unsafe { self.fn_table.$fn_name.get(self.lib_handle.as_ptr(), concat!(stringify!($fn_name), "\0").as_bytes()) };
                    func.map(|f| f($($arg_id),*) )
                }
            )*
        }
    };
}

cuda_function_declarations!(emit_cuda_fn_table);