Reorganize and refactor source tree (#324)
With RFC 2325 looking close to being accepted, I took a crack at reorganizing this repository to being more amenable for inclusion in libstd/libcore. My current plan is to add stdsimd as a submodule in rust-lang/rust and then use `#[path]` to include the modules directly into libstd/libcore. Before this commit, however, the source code of coresimd/stdsimd themselves were not quite ready for this. Imports wouldn't compile for one reason or another, and the organization was also different than the RFC itself! In addition to moving a lot of files around, this commit has the following major changes: * The `cfg_feature_enabled!` macro is now renamed to `is_target_feature_detected!` * The `vendor` module is now called `arch`. * Under the `arch` module is a suite of modules like `x86`, `x86_64`, etc. One per `cfg!(target_arch)`. * The `is_target_feature_detected!` macro was removed from coresimd. Unfortunately libcore has no ability to export unstable macros, so for now all feature detection is canonicalized in stdsimd. The `coresimd` and `stdsimd` crates have been updated to the planned organization in RFC 2325 as well. The runtime bits saw the largest amount of refactoring, seeing a good deal of simplification without the core/std split.
This commit is contained in:
100
library/stdarch/crates/simd-test-macro/src/lib.rs
Normal file
100
library/stdarch/crates/simd-test-macro/src/lib.rs
Normal file
@@ -0,0 +1,100 @@
|
||||
//! Implementation of the `#[simd_test]` macro
|
||||
//!
|
||||
//! This macro expands to a `#[test]` function which tests the local machine
|
||||
//! for the appropriate cfg before calling the inner test function.
|
||||
|
||||
#![feature(proc_macro)]
|
||||
|
||||
extern crate proc_macro;
|
||||
extern crate proc_macro2;
|
||||
#[macro_use]
|
||||
extern crate quote;
|
||||
|
||||
use proc_macro2::{Term, TokenNode, TokenStream, TokenTree};
|
||||
use proc_macro2::Literal;
|
||||
|
||||
fn string(s: &str) -> TokenTree {
|
||||
TokenNode::Literal(Literal::string(s)).into()
|
||||
}
|
||||
|
||||
#[proc_macro_attribute]
|
||||
pub fn simd_test(
|
||||
attr: proc_macro::TokenStream, item: proc_macro::TokenStream
|
||||
) -> proc_macro::TokenStream {
|
||||
let tokens = TokenStream::from(attr).into_iter().collect::<Vec<_>>();
|
||||
if tokens.len() != 2 {
|
||||
panic!("expected #[simd_test = \"feature\"]");
|
||||
}
|
||||
match tokens[0].kind {
|
||||
TokenNode::Op('=', _) => {}
|
||||
_ => panic!("expected #[simd_test = \"feature\"]"),
|
||||
}
|
||||
let target_features = match tokens[1].kind {
|
||||
TokenNode::Literal(ref l) => l.to_string(),
|
||||
_ => panic!("expected #[simd_test = \"feature\"]"),
|
||||
};
|
||||
let target_features: Vec<String> = target_features
|
||||
.replace('"', "")
|
||||
.replace('+', "")
|
||||
.split(',')
|
||||
.map(|v| String::from(v))
|
||||
.collect();
|
||||
|
||||
let enable_feature = match tokens[1].kind {
|
||||
TokenNode::Literal(ref l) => l.to_string(),
|
||||
_ => panic!("expected #[simd_test = \"feature\"]"),
|
||||
};
|
||||
let enable_feature = enable_feature
|
||||
.trim_left_matches('"')
|
||||
.trim_right_matches('"');
|
||||
let enable_feature = string(enable_feature);
|
||||
let item = TokenStream::from(item);
|
||||
let name = find_name(item.clone());
|
||||
|
||||
let name: TokenStream = name.as_str().parse().unwrap();
|
||||
|
||||
let mut cfg_target_features = quote::Tokens::new();
|
||||
use quote::ToTokens;
|
||||
for feature in target_features {
|
||||
let q = quote_spanned! {
|
||||
proc_macro2::Span::call_site() =>
|
||||
is_target_feature_detected!(#feature) &&
|
||||
};
|
||||
q.to_tokens(&mut cfg_target_features);
|
||||
}
|
||||
let q = quote!{ true };
|
||||
q.to_tokens(&mut cfg_target_features);
|
||||
|
||||
let ret: TokenStream = quote_spanned! {
|
||||
proc_macro2::Span::call_site() =>
|
||||
#[allow(non_snake_case)]
|
||||
#[test]
|
||||
fn #name() {
|
||||
if #cfg_target_features {
|
||||
return unsafe { #name() };
|
||||
} else {
|
||||
::stdsimd_test::assert_skip_test_ok(stringify!(#name));
|
||||
}
|
||||
|
||||
#[target_feature(enable = #enable_feature)]
|
||||
#item
|
||||
}
|
||||
}.into();
|
||||
ret.into()
|
||||
}
|
||||
|
||||
fn find_name(item: TokenStream) -> Term {
|
||||
let mut tokens = item.into_iter();
|
||||
while let Some(tok) = tokens.next() {
|
||||
if let TokenNode::Term(word) = tok.kind {
|
||||
if word.as_str() == "fn" {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
match tokens.next().map(|t| t.kind) {
|
||||
Some(TokenNode::Term(word)) => word,
|
||||
_ => panic!("failed to find function name"),
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user