about summary refs log tree commit diff
path: root/library/stdarch/crates/assert-instr-macro/src
diff options
context:
space:
mode:
authorAlex Crichton <alex@alexcrichton.com>2018-12-13 20:17:30 -0600
committerGitHub <noreply@github.com>2018-12-13 20:17:30 -0600
commitcb921381c42712e6098839543d80181c30b87483 (patch)
tree88f60a95ae0addce423df63599b8c1394b02e236 /library/stdarch/crates/assert-instr-macro/src
parent591ce8fe6fc784d493734ea9092b995426d22667 (diff)
downloadrust-cb921381c42712e6098839543d80181c30b87483.tar.gz
rust-cb921381c42712e6098839543d80181c30b87483.zip
Rewrite simd128 and wasm support (#620)
* Update representation of `v128`
* Rename everything with new naming convention of underscores and no
  modules/impls
* Remove no longer necessary `wasm_simd128` feature
* Remove `#[target_feature]` attributes (use `#[cfg]` instead)
* Update `assert_instr` tests
* Update some implementations as LLVM has evolved
* Allow some more esoteric syntax in `#[assert_instr]`
* Adjust the safety of APIs where appropriate
* Remove macros in favor of hand-coded implementations
* Comment out the tests for now as there's no known runtime for these
  yet
Diffstat (limited to 'library/stdarch/crates/assert-instr-macro/src')
-rw-r--r--library/stdarch/crates/assert-instr-macro/src/lib.rs52
1 files changed, 43 insertions, 9 deletions
diff --git a/library/stdarch/crates/assert-instr-macro/src/lib.rs b/library/stdarch/crates/assert-instr-macro/src/lib.rs
index 43a8b8a7e62..eba00e6b2b4 100644
--- a/library/stdarch/crates/assert-instr-macro/src/lib.rs
+++ b/library/stdarch/crates/assert-instr-macro/src/lib.rs
@@ -22,8 +22,14 @@ pub fn assert_instr(
     attr: proc_macro::TokenStream,
     item: proc_macro::TokenStream,
 ) -> proc_macro::TokenStream {
-    let invoc = syn::parse::<Invoc>(attr).expect("expected #[assert_instr(instr, a = b, ...)]");
-    let item = syn::parse::<syn::Item>(item).expect("must be attached to an item");
+    let invoc = match syn::parse::<Invoc>(attr) {
+        Ok(s) => s,
+        Err(e) => return e.to_compile_error().into(),
+    };
+    let item = match syn::parse::<syn::Item>(item) {
+        Ok(s) => s,
+        Err(e) => return e.to_compile_error().into(),
+    };
     let func = match item {
         syn::Item::Fn(ref f) => f,
         _ => panic!("must be attached to a function"),
@@ -39,6 +45,8 @@ pub fn assert_instr(
 
     let instr_str = instr
         .replace('.', "_")
+        .replace('/', "_")
+        .replace(':', "_")
         .replace(|c: char| c.is_whitespace(), "");
     let assert_name = syn::Ident::new(&format!("assert_{}_{}", name, instr_str), name.span());
     let shim_name = syn::Ident::new(&format!("{}_shim", name), name.span());
@@ -143,18 +151,44 @@ struct Invoc {
 
 impl syn::parse::Parse for Invoc {
     fn parse(input: syn::parse::ParseStream) -> syn::parse::Result<Self> {
-        use syn::Token;
-
-        let instr = match input.parse::<syn::Ident>() {
-            Ok(s) => s.to_string(),
-            Err(_) => input.parse::<syn::LitStr>()?.value(),
-        };
+        use syn::{ext::IdentExt, Token};
+
+        let mut instr = String::new();
+        while !input.is_empty() {
+            if input.parse::<Token![,]>().is_ok() {
+                break;
+            }
+            if let Ok(ident) = syn::Ident::parse_any(input) {
+                instr.push_str(&ident.to_string());
+                continue;
+            }
+            if input.parse::<Token![.]>().is_ok() {
+                instr.push_str(".");
+                continue;
+            }
+            if let Ok(s) = input.parse::<syn::LitStr>() {
+                instr.push_str(&s.value());
+                continue;
+            }
+            println!("{:?}", input.cursor().token_stream());
+            return Err(input.error("expected an instruction"));
+        }
+        if instr.len() == 0 {
+            return Err(input.error("expected an instruction before comma"));
+        }
         let mut args = Vec::new();
-        while input.parse::<Token![,]>().is_ok() {
+        while !input.is_empty() {
             let name = input.parse::<syn::Ident>()?;
             input.parse::<Token![=]>()?;
             let expr = input.parse::<syn::Expr>()?;
             args.push((name, expr));
+
+            if input.parse::<Token![,]>().is_err() {
+                if !input.is_empty() {
+                    return Err(input.error("extra tokens at end"));
+                }
+                break;
+            }
         }
         Ok(Self { instr, args })
     }