generic_simd_macros/
lib.rs

1extern crate proc_macro;
2use proc_macro::TokenStream;
3use quote::quote;
4use syn::{parse_macro_input, Ident, ItemFn};
5
6#[proc_macro_attribute]
7pub fn dispatch(args: TokenStream, input: TokenStream) -> TokenStream {
8    let ItemFn {
9        attrs,
10        vis,
11        sig,
12        block,
13    } = parse_macro_input!(input as ItemFn);
14    let feature = parse_macro_input!(args as Ident);
15
16    let build_fn = |wasm| {
17        let nightly = cfg!(feature = "nightly");
18        let clone_wasm = if nightly && wasm {
19            Some(quote! { #[clone(target = "wasm32+simd128")] })
20        } else {
21            None
22        };
23        let clone_arm = if nightly {
24            Some(quote! { #[clone(target = "aarch64+neon")] })
25        } else {
26            None
27        };
28        quote! {
29            #[generic_simd::multiversion::multiversion]
30            #[clone(target = "[x86|x86_64]+avx")]
31            #[clone(target = "[x86|x86_64]+sse4.1")]
32            #clone_wasm
33            #clone_arm
34            #[crate_path(path = "generic_simd::multiversion")]
35            #(#attrs)*
36            #vis
37            #sig
38            {
39                #[target_cfg(target = "[x86|x86_64]+sse4.1")]
40                let #feature = unsafe { <generic_simd::arch::x86::Sse as generic_simd::arch::Token>::new_unchecked() };
41
42                #[target_cfg(target = "[x86|x86_64]+avx")]
43                let #feature = unsafe { <generic_simd::arch::x86::Avx as generic_simd::arch::Token>::new_unchecked() };
44
45                #[target_cfg(target = "wasm32+simd128")]
46                let #feature = unsafe { <generic_simd::arch::wasm::Simd128 as generic_simd::arch::Token>::new_unchecked() };
47
48                #[target_cfg(target = "[arm|aarch64]+neon")]
49                let #feature = unsafe { <generic_simd::arch::arm::Neon as generic_simd::arch::Token>::new_unchecked() };
50
51                #[target_cfg(not(any(
52                    target = "[x86|x86_64]+sse4.1",
53                    target = "[x86|x86_64]+avx",
54                    target = "[arm|aarch64]+neon",
55                    target = "wasm32+simd128",
56                )))]
57                let #feature = <generic_simd::arch::generic::Generic as generic_simd::arch::Token>::new().unwrap();
58
59                #block
60            }
61        }
62    };
63    let normal = build_fn(false);
64    let with_wasm = build_fn(true);
65    let output = quote! {
66        #[cfg(all(target_arch = "wasm32", target_feature = "simd128"))]
67        #with_wasm
68
69        #[cfg(not(all(target_arch = "wasm32", target_feature = "simd128"),))]
70        #normal
71    };
72    output.into()
73}