Skip to content

Commit a666c38

Browse files
edited readme
1 parent 49cf741 commit a666c38

File tree

2 files changed

+16655
-480
lines changed

2 files changed

+16655
-480
lines changed

testable-simd-models/README.md

Lines changed: 99 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -125,10 +125,11 @@ pub fn phaddw(a: i16x16, b: i16x16) -> i16x16 {
125125

126126
### Modeling defined intrinsics semi-automatically
127127

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
132133
needed by hand.
133134

134135
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 {
176177
```
177178

178179
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+
```
181193

182194
For other intrinsics, we sometimes need to make more changes. Since our model of the builtin intrinsics
183195
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
224236
test case generated from the testable model and then fixed by [our
225237
PR](https://github.com/rust-lang/stdarch/pull/1823) in the 2025-06-30
226238
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

Comments
 (0)