@@ -5,11 +5,12 @@ extern crate quote;
55#[ macro_use]
66extern crate syn;
77
8+ use proc_macro:: TokenStream ;
9+ use proc_macro2:: Span ;
810use std:: fs:: File ;
911use std:: io:: Read ;
1012use std:: path:: Path ;
11-
12- use proc_macro:: TokenStream ;
13+ use syn:: ext:: IdentExt ;
1314
1415#[ proc_macro]
1516pub fn x86_functions ( input : TokenStream ) -> TokenStream {
@@ -91,7 +92,7 @@ fn functions(input: TokenStream, dirs: &[&str]) -> TokenStream {
9192 arguments: & [ #( #arguments) , * ] ,
9293 ret: #ret,
9394 target_feature: #target_feature,
94- instrs: & [ #( stringify! ( #instrs) ) , * ] ,
95+ instrs: & [ #( #instrs) , * ] ,
9596 file: stringify!( #path) ,
9697 required_const: & [ #( #required_const) , * ] ,
9798 }
@@ -263,35 +264,54 @@ fn walk(root: &Path, files: &mut Vec<(syn::File, String)>) {
263264 }
264265}
265266
266- fn find_instrs ( attrs : & [ syn:: Attribute ] ) -> Vec < syn :: Ident > {
267- attrs
267+ fn find_instrs ( attrs : & [ syn:: Attribute ] ) -> Vec < String > {
268+ return attrs
268269 . iter ( )
269- . filter_map ( |a| a. interpret_meta ( ) )
270- . filter_map ( |a| match a {
271- syn:: Meta :: List ( i) => {
272- if i. ident == "cfg_attr" {
273- i. nested . into_iter ( ) . nth ( 1 )
274- } else {
275- None
276- }
270+ . filter ( |a| a. path == syn:: Ident :: new ( "cfg_attr" , Span :: call_site ( ) ) . into ( ) )
271+ . filter_map ( |a| syn:: parse2 :: < AssertInstr > ( a. tts . clone ( ) ) . ok ( ) )
272+ . map ( |a| a. instr )
273+ . collect ( ) ;
274+
275+ struct AssertInstr {
276+ instr : String ,
277+ }
278+
279+ // A small custom parser to parse out the instruction in `assert_instr`.
280+ //
281+ // TODO: should probably just reuse `Invoc` from the `assert-instr-macro`
282+ // crate.
283+ impl syn:: parse:: Parse for AssertInstr {
284+ fn parse ( content : syn:: parse:: ParseStream ) -> syn:: parse:: Result < Self > {
285+ let input;
286+ parenthesized ! ( input in content) ;
287+ drop ( input. parse :: < syn:: Meta > ( ) ?) ;
288+ drop ( input. parse :: < Token ! [ , ] > ( ) ?) ;
289+ let ident = input. parse :: < syn:: Ident > ( ) ?;
290+ if ident != "assert_instr" {
291+ return Err ( input. error ( "expected `assert_instr`" ) ) ;
277292 }
278- _ => None ,
279- } )
280- . filter_map ( |nested| match nested {
281- syn:: NestedMeta :: Meta ( syn:: Meta :: List ( i) ) => {
282- if i. ident == "assert_instr" {
283- i. nested . into_iter ( ) . next ( )
293+ let instrs;
294+ parenthesized ! ( instrs in input) ;
295+
296+ let mut instr = String :: new ( ) ;
297+ while !instrs. is_empty ( ) {
298+ if let Ok ( lit) = instrs. parse :: < syn:: LitStr > ( ) {
299+ instr. push_str ( & lit. value ( ) ) ;
300+ } else if let Ok ( ident) = instrs. call ( syn:: Ident :: parse_any) {
301+ instr. push_str ( & ident. to_string ( ) ) ;
302+ } else if instrs. parse :: < Token ! [ . ] > ( ) . is_ok ( ) {
303+ instr. push_str ( "." ) ;
304+ } else if instrs. parse :: < Token ! [ , ] > ( ) . is_ok ( ) {
305+ // consume everything remaining
306+ drop ( instrs. parse :: < proc_macro2:: TokenStream > ( ) ) ;
307+ break ;
284308 } else {
285- None
309+ return Err ( input . error ( "failed to parse instruction" ) ) ;
286310 }
287311 }
288- _ => None ,
289- } )
290- . filter_map ( |nested| match nested {
291- syn:: NestedMeta :: Meta ( syn:: Meta :: Word ( i) ) => Some ( i) ,
292- _ => None ,
293- } )
294- . collect ( )
312+ Ok ( AssertInstr { instr } )
313+ }
314+ }
295315}
296316
297317fn find_target_feature ( attrs : & [ syn:: Attribute ] ) -> Option < syn:: Lit > {
0 commit comments