-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathlib.rs
More file actions
84 lines (71 loc) · 2.78 KB
/
Copy pathlib.rs
File metadata and controls
84 lines (71 loc) · 2.78 KB
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
80
81
82
83
84
use proc_macro::TokenStream;
use proc_macro_crate::{FoundCrate, crate_name};
use quote::{format_ident, quote};
use syn::{
Data, DataStruct, DeriveInput, Error, Field, Ident, LitInt, WhereClause, parse_macro_input,
parse_quote,
};
fn find_oneapi() -> Ident {
let crate_name = crate_name("oneapi_rs").expect("oneapi_rs is present in Cargo.toml");
match crate_name {
FoundCrate::Itself => format_ident!("crate"),
FoundCrate::Name(name) => format_ident!("{name}"),
}
}
/// Derive macro generating an impl of the `KernelArgumentList` trait for a given struct.
#[proc_macro_derive(KernelArgumentList)]
pub fn derive_kernel_argument_list(input: TokenStream) -> TokenStream {
let mut input = parse_macro_input!(input as DeriveInput);
let oneapi = find_oneapi();
let Data::Struct(data) = &input.data else {
return Error::new_spanned(input, "This derive macro only works on structs.")
.into_compile_error()
.into();
};
expand_where_clause(input.generics.make_where_clause(), data, &oneapi);
let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();
let ident = input.ident;
let argc = data.fields.len();
let members = data.fields.members();
let expanded = quote! {
unsafe impl #impl_generics #oneapi::kernel::KernelArgumentList<#argc>
for #ident #ty_generics #where_clause {
unsafe fn as_raw_arg_list(&self) -> [&[u8]; #argc] {
[ #(unsafe { self.#members.as_raw_arg() }),* ]
}
}
};
TokenStream::from(expanded)
}
fn expand_where_clause(where_clause: &mut WhereClause, data: &DataStruct, oneapi: &Ident) {
for Field { ty, .. } in &data.fields {
where_clause
.predicates
.push(parse_quote!(#ty: #oneapi::kernel::KernelArgument));
}
}
fn get_single_tuple_impl(argc: usize) -> proc_macro2::TokenStream {
let iter = { 0..argc }.map(syn::Index::from);
let types = { 0..argc }
.map(|i| format_ident!("T{i}"))
.collect::<Vec<_>>();
quote! {
unsafe impl<#(#types),*> crate::kernel::KernelArgumentList<#argc> for (#(#types),*)
where #(#types: crate::kernel::KernelArgument),* {
unsafe fn as_raw_arg_list(&self) -> [&[u8]; #argc] {
[ #(unsafe { self.#iter.as_raw_arg() }),* ]
}
}
}
}
/// A macro that generates tuples from 2..N which implement the `KernelArgumentList` trait.
#[proc_macro]
pub fn impl_arg_list_for_tuples(input: TokenStream) -> TokenStream {
let input = parse_macro_input!(input as LitInt);
let argc = input.base10_parse::<usize>().unwrap();
let impls = { 2..=argc }.map(get_single_tuple_impl);
let expanded = quote! {
#(#impls)*
};
TokenStream::from(expanded)
}