multiversion_macros/
lib.rs1extern crate proc_macro;
3
4mod cfg;
5mod dispatcher;
6mod match_target;
7mod multiversion;
8mod simd;
9mod target;
10mod util;
11
12use proc_macro2::TokenStream;
13use quote::{quote, ToTokens};
14use syn::{parse::Nothing, parse_macro_input, punctuated::Punctuated, ItemFn};
15
16#[proc_macro_attribute]
17pub fn multiversion(
18 attr: proc_macro::TokenStream,
19 input: proc_macro::TokenStream,
20) -> proc_macro::TokenStream {
21 let func = parse_macro_input!(input as ItemFn);
22 match multiversion::make_multiversioned_fn(attr.into(), func) {
23 Ok(tokens) => tokens.into_token_stream(),
24 Err(err) => err.to_compile_error(),
25 }
26 .into()
27}
28
29#[proc_macro_attribute]
30pub fn target(
31 attr: proc_macro::TokenStream,
32 input: proc_macro::TokenStream,
33) -> proc_macro::TokenStream {
34 let target = parse_macro_input!(attr as syn::LitStr);
35 let func = parse_macro_input!(input as ItemFn);
36 match target::make_target_fn(target, func) {
37 Ok(tokens) => tokens.into_token_stream(),
38 Err(err) => err.to_compile_error(),
39 }
40 .into()
41}
42
43#[proc_macro_attribute]
44pub fn inherit_target(
45 attr: proc_macro::TokenStream,
46 input: proc_macro::TokenStream,
47) -> proc_macro::TokenStream {
48 parse_macro_input!(attr as Nothing);
49 let func = parse_macro_input!(input as ItemFn);
50 quote! {
51 __multiversion::inherit_target! { #func }
52 }
53 .into()
54}
55
56#[proc_macro]
57pub fn selected_target(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
58 parse_macro_input!(input as Nothing);
59 quote! {
60 __multiversion::selected_target! {}
61 }
62 .into()
63}
64
65#[proc_macro_attribute]
66pub fn target_cfg(
67 attr: proc_macro::TokenStream,
68 input: proc_macro::TokenStream,
69) -> proc_macro::TokenStream {
70 let attr = TokenStream::from(attr);
71 let input = TokenStream::from(input);
72 quote! {
73 __multiversion::target_cfg!{ [#attr] #input }
74 }
75 .into()
76}
77
78#[proc_macro_attribute]
79pub fn target_cfg_attr(
80 attr: proc_macro::TokenStream,
81 input: proc_macro::TokenStream,
82) -> proc_macro::TokenStream {
83 let attr = TokenStream::from(attr);
84 let input = TokenStream::from(input);
85 quote! {
86 __multiversion::target_cfg_attr!{ [#attr] #input }
87 }
88 .into()
89}
90
91#[proc_macro]
92pub fn target_cfg_f(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
93 let input = TokenStream::from(input);
94 quote! {
95 __multiversion::target_cfg_f!{ #input }
96 }
97 .into()
98}
99
100#[proc_macro_attribute]
101pub fn target_cfg_impl(
102 attr: proc_macro::TokenStream,
103 input: proc_macro::TokenStream,
104) -> proc_macro::TokenStream {
105 let meta = parse_macro_input!(attr with Punctuated::parse_terminated);
106 let input = TokenStream::from(input);
107
108 match cfg::transform(meta) {
109 Ok(meta) => {
110 quote! {
111 #[cfg(#meta)]
112 #input
113 }
114 }
115 Err(err) => err.to_compile_error(),
116 }
117 .into()
118}
119
120#[proc_macro_attribute]
121pub fn target_cfg_attr_impl(
122 attr: proc_macro::TokenStream,
123 input: proc_macro::TokenStream,
124) -> proc_macro::TokenStream {
125 let mut meta = parse_macro_input!(attr with Punctuated::parse_terminated);
126 let input = TokenStream::from(input);
127
128 let attr = meta.pop().unwrap();
129 match cfg::transform(meta) {
130 Ok(meta) => {
131 quote! {
132 #[cfg_attr(#meta, #attr)]
133 #input
134 }
135 }
136 Err(err) => err.to_compile_error(),
137 }
138 .into()
139}
140
141#[proc_macro]
142pub fn target_cfg_f_impl(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
143 let meta = parse_macro_input!(input with Punctuated::parse_terminated);
144
145 match cfg::transform(meta) {
146 Ok(meta) => {
147 quote! {
148 ::core::cfg!(#meta)
149 }
150 }
151 Err(err) => err.to_compile_error(),
152 }
153 .into()
154}
155
156#[proc_macro]
157pub fn match_target(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
158 let input = TokenStream::from(input);
159 quote! {
160 __multiversion::match_target!{ #input }
161 }
162 .into()
163}
164
165#[proc_macro]
166pub fn match_target_impl(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
167 let match_target = parse_macro_input!(input as match_target::MatchTarget);
168 match_target.into_token_stream().into()
169}