@@ -5,11 +5,12 @@ extern crate quote;
5
5
#[ macro_use]
6
6
extern crate syn;
7
7
8
+ use proc_macro:: TokenStream ;
9
+ use proc_macro2:: Span ;
8
10
use std:: fs:: File ;
9
11
use std:: io:: Read ;
10
12
use std:: path:: Path ;
11
-
12
- use proc_macro:: TokenStream ;
13
+ use syn:: ext:: IdentExt ;
13
14
14
15
#[ proc_macro]
15
16
pub fn x86_functions ( input : TokenStream ) -> TokenStream {
@@ -91,7 +92,7 @@ fn functions(input: TokenStream, dirs: &[&str]) -> TokenStream {
91
92
arguments: & [ #( #arguments) , * ] ,
92
93
ret: #ret,
93
94
target_feature: #target_feature,
94
- instrs: & [ #( stringify! ( #instrs) ) , * ] ,
95
+ instrs: & [ #( #instrs) , * ] ,
95
96
file: stringify!( #path) ,
96
97
required_const: & [ #( #required_const) , * ] ,
97
98
}
@@ -263,35 +264,54 @@ fn walk(root: &Path, files: &mut Vec<(syn::File, String)>) {
263
264
}
264
265
}
265
266
266
- fn find_instrs ( attrs : & [ syn:: Attribute ] ) -> Vec < syn :: Ident > {
267
- attrs
267
+ fn find_instrs ( attrs : & [ syn:: Attribute ] ) -> Vec < String > {
268
+ return attrs
268
269
. 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`" ) ) ;
277
292
}
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 ;
284
308
} else {
285
- None
309
+ return Err ( input . error ( "failed to parse instruction" ) ) ;
286
310
}
287
311
}
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
+ }
295
315
}
296
316
297
317
fn find_target_feature ( attrs : & [ syn:: Attribute ] ) -> Option < syn:: Lit > {
0 commit comments