@@ -125,10 +125,11 @@ pub fn phaddw(a: i16x16, b: i16x16) -> i16x16 {
125
125
126
126
### Modeling defined intrinsics semi-automatically
127
127
128
- To model a defined intrinsic, we essentially copy the Rust code of
129
- the intrinsic from ` core::arch ` and adapt it to use our underlying abstractions. The
130
- changes needed to the code are sometimes scriptable, and indeed most
131
- of our models were generated from a script, but some changes are still
128
+ To model a defined intrinsic, we essentially copy the Rust code of the
129
+ intrinsic from ` core::arch ` and adapt it to use our underlying
130
+ abstractions. The changes needed to the code are sometimes
131
+ scriptable, and indeed most of our models were generated from a script
132
+ (see the ANNEX at the bottom of this file), but some changes are still
132
133
needed by hand.
133
134
134
135
For example, let us say the intrinsic we are modeling is
@@ -176,8 +177,19 @@ pub fn _mm256_bsrli_epi128<const IMM8: i32>(a: __m256i) -> __m256i {
176
177
```
177
178
178
179
Thus, we then go to ` core_arch/x86/models/avx2.rs ` , and add this implementation.
179
- The only change it requires here is that the ` simd_shuffle ` macro is a function in our model,
180
- and we discard all the function attributes.
180
+ The only changes it requires here are that the ` simd_shuffle ` macro is a function in our model,
181
+ the ` ZERO ` constant is now a function, and we discard all the function attributes.
182
+
183
+ The exact diff between the original and edited code for this function is:
184
+
185
+ ``` diff
186
+ 13,14c13,14
187
+ < let r: i8x32 = simd_shuffle(
188
+ < i8x32::ZERO(),
189
+ ---
190
+ > let r: i8x32 = simd_shuffle!(
191
+ > i8x32::ZERO,
192
+ ```
181
193
182
194
For other intrinsics, we sometimes need to make more changes. Since our model of the builtin intrinsics
183
195
is more precise concerning the type of their arguments compared to their Rust counterparts, we
@@ -224,3 +236,84 @@ us](https://github.com/rust-lang/stdarch/issues/1822) using a failing
224
236
test case generated from the testable model and then fixed by [ our
225
237
PR] ( https://github.com/rust-lang/stdarch/pull/1823 ) in the 2025-06-30
226
238
version of ` stdarch ` .
239
+
240
+
241
+ ## ANNEX: Extraction Script
242
+
243
+ The following Rust program is a simple script that uses the ` syn ` crate to process an input Rust file
244
+ containing SIMD intrinsics into one suitable for the models described in this document. This code
245
+ is provided as illustration; for each set of core libraries we wish to model and test, there will
246
+ likely be need for a similar (or extended) script to automate the modeling process.
247
+
248
+ ``` rust
249
+ use syn :: * ;
250
+ use std :: fs;
251
+ use std :: env;
252
+
253
+ fn extract_model (input_file_path : & str , output_file_path : & str ) -> Result <()> {
254
+ let source_code = fs :: read_to_string (input_file_path ). expect (" unable to read file" );
255
+ let mut syntax_tree : File = parse_file (& source_code )? ;
256
+
257
+ syntax_tree . items. retain (| item |
258
+ match item {
259
+ Item :: Use (_ ) => false ,
260
+ _ => true
261
+ }
262
+ );
263
+
264
+ // Clear attributes from the file's top-level items
265
+ for item in & mut syntax_tree . items {
266
+ match item {
267
+ Item :: Const (const_item ) => {
268
+ const_item . attrs. retain (| attr | attr . path (). is_ident (" doc" ));
269
+ },
270
+ Item :: Fn (item_fn ) => {
271
+ item_fn . attrs. retain (| attr | attr . path (). is_ident (" doc" ));
272
+ item_fn . block. stmts. retain (| stmt |
273
+ match stmt {
274
+ Stmt :: Item (Item :: ForeignMod (_ )) => false ,
275
+ _ => true
276
+ }
277
+ );
278
+ for stmt in & mut item_fn . block. stmts {
279
+ match stmt {
280
+ Stmt :: Expr (Expr :: Unsafe (u ), tok ) => * stmt = Stmt :: Expr (Expr :: Block (
281
+ ExprBlock {attrs : Vec :: new (), label : None , block : u . block. clone ()}), * tok ),
282
+ _ => ()
283
+ }
284
+ }
285
+ },
286
+ Item :: Struct (item_struct ) => {
287
+ item_struct . attrs. clear ();
288
+ for field in & mut item_struct . fields {
289
+ field . attrs. retain (| attr | attr . path (). is_ident (" doc" ));
290
+ }
291
+ },
292
+ Item :: Enum (item_enum ) => {
293
+ item_enum . attrs. clear ();
294
+ for variant in & mut item_enum . variants {
295
+ variant . attrs. retain (| attr | attr . path (). is_ident (" doc" ));
296
+ }
297
+ },
298
+ // Add more cases for other Item types (e.g., Item::Mod, Item::Impl, etc.)
299
+ _ => {
300
+ // For other item types, if they have an 'attrs' field, clear it.
301
+ // This requires more specific matching or a helper trait.
302
+ }
303
+ }
304
+ }
305
+
306
+ let formatted_string = prettyplease :: unparse (& syntax_tree );
307
+ fs :: write (output_file_path , formatted_string ). expect (" unable to write file" );
308
+
309
+ Ok (())
310
+ }
311
+
312
+ fn main () -> Result <()> {
313
+ let args : Vec <String > = env :: args (). collect ();
314
+ if args . len () < 3 {
315
+ println! (" usage: modelize <path to input Rust file> <path to output Rust file>" )
316
+ }
317
+ extract_model (& args [1 ], & args [2 ])
318
+ }
319
+ ```
0 commit comments