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
extern crate proc_macro; use proc_macro::TokenStream; use quote::quote; use syn::{parse_macro_input, Ident, ItemFn}; #[proc_macro_attribute] pub fn dispatch(args: TokenStream, input: TokenStream) -> TokenStream { let ItemFn { attrs, vis, sig, block, } = parse_macro_input!(input as ItemFn); let feature = parse_macro_input!(args as Ident); let build_fn = |wasm| { let nightly = cfg!(feature = "nightly"); let clone_wasm = if nightly && wasm { Some(quote! { #[clone(target = "wasm32+simd128")] }) } else { None }; let clone_arm = if nightly { Some(quote! { #[clone(target = "aarch64+neon")] }) } else { None }; quote! { #[generic_simd::multiversion::multiversion] #[clone(target = "[x86|x86_64]+avx")] #[clone(target = "[x86|x86_64]+sse4.1")] #clone_wasm #clone_arm #[crate_path(path = "generic_simd::multiversion")] #(#attrs)* #vis #sig { #[target_cfg(target = "[x86|x86_64]+sse4.1")] let #feature = unsafe { <generic_simd::arch::x86::Sse as generic_simd::arch::Token>::new_unchecked() }; #[target_cfg(target = "[x86|x86_64]+avx")] let #feature = unsafe { <generic_simd::arch::x86::Avx as generic_simd::arch::Token>::new_unchecked() }; #[target_cfg(target = "wasm32+simd128")] let #feature = unsafe { <generic_simd::arch::wasm::Simd128 as generic_simd::arch::Token>::new_unchecked() }; #[target_cfg(target = "[arm|aarch64]+neon")] let #feature = unsafe { <generic_simd::arch::arm::Neon as generic_simd::arch::Token>::new_unchecked() }; #[target_cfg(not(any( target = "[x86|x86_64]+sse4.1", target = "[x86|x86_64]+avx", target = "[arm|aarch64]+neon", target = "wasm32+simd128", )))] let #feature = <generic_simd::arch::generic::Generic as generic_simd::arch::Token>::new().unwrap(); #block } } }; let normal = build_fn(false); let with_wasm = build_fn(true); let output = quote! { #[cfg(all(target_arch = "wasm32", target_feature = "simd128"))] #with_wasm #[cfg(not(all(target_arch = "wasm32", target_feature = "simd128"),))] #normal }; output.into() }